bash -c "$(curl -fsSL …/scripts/quick_start.sh)" 一条命令: 架构自检(x86_64/arm64)→ 发布包下载(默认 Gitea Release,可镜像)→ 随机密钥生成持久化 → systemd 开机自启 → 健康等待 → 打印访问地址/初始密码/常用命令;重复执行即升级(数据自动备份)。 CentOS 7 真机验证:安装、登录、文档/落地页、升级幂等全通。 配套 upload-release.sh(make dist 后一键发布双架构包到 Gitea Release);README/手册/CHANGELOG 同步。
132 lines
5.2 KiB
Bash
Executable File
132 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ============================================================================
|
|
# LokiStack 一键安装(Linux x86_64 / arm64)
|
|
#
|
|
# 用法:
|
|
# bash -c "$(curl -fsSL https://gitea.91ai.io/rlwj-lab/LokiStack/raw/main/scripts/quick_start.sh)"
|
|
#
|
|
# 可覆盖(环境变量):
|
|
# INSTALL_DIR 安装目录,默认 /opt/lokistack
|
|
# VERSION 版本 tag,默认 latest(自动解析最新 release)
|
|
# BASE_URL 下载源,默认 Gitea Release
|
|
# PORT 服务端口,默认 8080
|
|
# SKIP_SERVICE=1 仅解压不注册 systemd(调试用)
|
|
# ============================================================================
|
|
set -euo pipefail
|
|
|
|
REPO="rlwj-lab/LokiStack"
|
|
GITEA="https://gitea.91ai.io"
|
|
INSTALL_DIR="${INSTALL_DIR:-/opt/lokistack}"
|
|
VERSION="${VERSION:-latest}"
|
|
BASE_URL="${BASE_URL:-${GITEA}}"
|
|
PORT="${PORT:-8080}"
|
|
|
|
info() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
|
|
ok() { printf '\033[1;32m✅\033[0m %s\n' "$*"; }
|
|
warn() { printf '\033[1;33m⚠️\033[0m %s\n' "$*"; }
|
|
die() { printf '\033[1;31m❌\033[0m %s\n' "$*" >&2; exit 1; }
|
|
|
|
# ---- 1. 环境自检 ----
|
|
[ "$(id -u)" = "0" ] || die "请用 root 运行(sudo bash $0)"
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) ARCH="amd64" ;;
|
|
aarch64|arm64) ARCH="arm64" ;;
|
|
*) die "不支持的架构: $(uname -m)(支持 x86_64 / arm64)" ;;
|
|
esac
|
|
command -v curl >/dev/null || die "缺少 curl,请先安装(apt/yum install curl)"
|
|
command -v tar >/dev/null || die "缺少 tar,请先安装"
|
|
if [ "${SKIP_SERVICE:-0}" != "1" ]; then
|
|
command -v systemctl >/dev/null || die "未检测到 systemd,可设 SKIP_SERVICE=1 手动运行"
|
|
fi
|
|
ok "环境就绪: $(uname -m) -> ${ARCH}, $(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d'"' -f2 || echo Linux)"
|
|
|
|
# ---- 2. 解析版本并下载 ----
|
|
if [ "$VERSION" = "latest" ]; then
|
|
info "解析最新版本..."
|
|
VERSION="$(curl -fsSL "$GITEA/api/v1/repos/$REPO/releases/latest" | grep -o '"tag_name":"[^"]*"' | head -1 | cut -d'"' -f4)"
|
|
[ -n "$VERSION" ] || die "无法获取最新版本(检查网络或手动指定 VERSION=vX.Y.Z)"
|
|
fi
|
|
PKG="lokistack-linux-${ARCH}.tar.gz"
|
|
URL="$BASE_URL/$REPO/releases/download/$VERSION/$PKG"
|
|
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
|
|
info "下载 ${URL}"
|
|
curl -fSL --retry 3 --connect-timeout 10 -o "$TMP/$PKG" "$URL" || die "下载失败(可设 BASE_URL 指定镜像源)"
|
|
ok "下载完成: $(du -h "$TMP/$PKG" | cut -f1)"
|
|
|
|
# ---- 3. 安装(重复执行 = 升级) ----
|
|
if systemctl is-active lokistack >/dev/null 2>&1; then
|
|
info "检测到已有 LokiStack 服务,执行升级..."
|
|
systemctl stop lokistack || true
|
|
[ -d "$INSTALL_DIR/data" ] && cp -r "$INSTALL_DIR/data" "${INSTALL_DIR}/data.bak.$(date +%Y%m%d%H%M%S)"
|
|
fi
|
|
mkdir -p "$INSTALL_DIR"
|
|
tar -xzf "$TMP/$PKG" -C "$TMP"
|
|
SRC="$TMP/lokistack-linux-${ARCH}"
|
|
mv "$SRC/lokistack" "$SRC/docs" "$SRC/homepage" "$SRC/README.md" "$INSTALL_DIR/" 2>/dev/null || true
|
|
chmod +x "$INSTALL_DIR/lokistack"
|
|
mkdir -p "$INSTALL_DIR/data"
|
|
ok "安装到 $INSTALL_DIR(数据目录 $INSTALL_DIR/data)"
|
|
|
|
# ---- 4. 密钥:自动生成随机密钥并持久化(显式已存在则不动) ----
|
|
SECRETS="$INSTALL_DIR/data/.secrets.env"
|
|
gen() { head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n'; }
|
|
if [ ! -f "$SECRETS" ]; then
|
|
umask 077
|
|
{ echo "# LokiStack 自动生成,删除后重新执行脚本可重置"
|
|
echo "JWT_SECRET=$(gen)"; echo "ENCRYPTION_KEY=$(gen)"; } > "$SECRETS"
|
|
ok "已生成随机密钥: $SECRETS"
|
|
else
|
|
ok "沿用已有密钥: $SECRETS"
|
|
fi
|
|
|
|
# ---- 5. systemd 服务 ----
|
|
if [ "${SKIP_SERVICE:-0}" != "1" ]; then
|
|
cat > /etc/systemd/system/lokistack.service <<UNIT
|
|
[Unit]
|
|
Description=LokiStack - Loki 日志管理平台
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
WorkingDirectory=$INSTALL_DIR
|
|
EnvironmentFile=$SECRETS
|
|
Environment=DATA_DIR=$INSTALL_DIR/data
|
|
Environment=SERVER_PORT=$PORT
|
|
ExecStart=$INSTALL_DIR/lokistack
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
LimitNOFILE=65535
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
UNIT
|
|
systemctl daemon-reload
|
|
systemctl enable --now lokistack
|
|
ok "服务已启动并设为开机自启"
|
|
fi
|
|
|
|
# ---- 6. 等待健康检查并输出摘要 ----
|
|
info "等待服务就绪..."
|
|
for i in $(seq 1 30); do
|
|
if curl -fs -o /dev/null "http://127.0.0.1:$PORT/api/v1/health" 2>/dev/null; then break; fi
|
|
sleep 1
|
|
[ "$i" = "30" ] && warn "服务 30s 内未就绪,请查看: journalctl -u lokistack -e"
|
|
done
|
|
|
|
IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
|
PASS_FILE="$INSTALL_DIR/data/initial-admin-password.txt"
|
|
echo ""
|
|
printf '\033[1;32m================================================\033[0m\n'
|
|
printf ' LokiStack 安装完成!\n'
|
|
printf '\033[1;32m================================================\033[0m\n'
|
|
printf ' 访问地址: http://%s:%s\n' "${IP:-<服务器IP>}" "$PORT"
|
|
printf ' 初始账号: admin\n'
|
|
[ -f "$PASS_FILE" ] && printf ' 初始密码: %s\n' "$(cat "$PASS_FILE")" || printf ' 初始密码: 见 %s\n' "$PASS_FILE"
|
|
printf ' 用户手册: http://%s:%s/docs/\n' "${IP:-<服务器IP>}" "$PORT"
|
|
printf '\n 常用命令:\n'
|
|
printf ' systemctl status lokistack # 状态\n'
|
|
printf ' journalctl -u lokistack -f # 日志\n'
|
|
printf ' 重新执行本脚本 # 升级(数据自动备份)\n'
|
|
printf '\033[1;32m================================================\033[0m\n'
|