fix(deploy): install.sh 不再依赖 sudo
用户实测报错:deploy/install.sh: line 173: sudo: command not found 本脚本已经强制要求 root 权限,用 sudo 降权到服务用户本就多余, 且部分服务器(尤其精简系统/容器)根本没有安装 sudo。 - 新增 as_service_user():runuser → setpriv → su 依次回退, 并在三者都不可用时给出明确错误 - 替换全部 sudo -u 调用(npm ci / npm install / npm run build / 迁移) - 新增 http_get() / http_ok():curl → wget → node fetch 依次回退, 健康检查不再强依赖 curl - 启动前检查 systemctl(本部署依赖 systemd),缺失时给出可操作提示 - 修正 install.sh / uninstall.sh 中所有「用 sudo 执行」的提示文案 实测(桩替换 runuser 验证分派与参数传递): 有 runuser:runuser -u opendance -- npm ci --omit=dev --loglevel=error 仅 su:正确回退到 su HTTP:curl 路径与 node fetch 回退路径返回一致
This commit is contained in:
+49
-9
@@ -37,8 +37,46 @@ log() { printf '\033[1;34m[install]\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m[error]\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# 以服务用户身份执行命令。
|
||||
# 本脚本已要求 root,因此**不使用 sudo**(部分服务器根本没装 sudo,
|
||||
# 且 root 降权本来也不需要它)。优先 runuser,其次 setpriv,最后 su。
|
||||
as_service_user() {
|
||||
if command -v runuser >/dev/null 2>&1; then
|
||||
runuser -u "$SERVICE_USER" -- "$@"
|
||||
elif command -v setpriv >/dev/null 2>&1; then
|
||||
setpriv --reuid="$SERVICE_USER" --regid="$SERVICE_USER" --init-groups -- "$@"
|
||||
elif command -v su >/dev/null 2>&1; then
|
||||
su -s /bin/bash "$SERVICE_USER" -c "$(printf '%q ' "$@")"
|
||||
else
|
||||
die "无法以 $SERVICE_USER 身份执行命令:runuser / setpriv / su 均不可用"
|
||||
fi
|
||||
}
|
||||
|
||||
# HTTP GET,输出响应体。curl → wget → node(node 必有,且 22+ 自带 fetch)
|
||||
http_get() {
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsS -m 5 "$1"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O - -T 5 "$1"
|
||||
else
|
||||
"$NODE_BIN" -e 'fetch(process.argv[1]).then(r=>r.text()).then(t=>process.stdout.write(t)).catch(()=>process.exit(1))' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# 健康检查(只看成功与否)
|
||||
http_ok() {
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsS -m 3 "$1" >/dev/null 2>&1
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O /dev/null -T 3 "$1"
|
||||
else
|
||||
"$NODE_BIN" -e 'fetch(process.argv[1]).then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- 0. 前置检查 ----------
|
||||
[ "$(id -u)" -eq 0 ] || die "需要 root 权限(安装 systemd 服务与 nginx 站点):sudo bash deploy/install.sh"
|
||||
[ "$(id -u)" -eq 0 ] || die "需要 root 权限(安装 systemd 服务与 nginx 站点)。
|
||||
请以 root 身份执行,例如: su -c 'bash deploy/install.sh' 或 sudo bash deploy/install.sh"
|
||||
|
||||
[ -f deploy/.env ] || die "缺少 deploy/.env,请先:
|
||||
cp deploy/.env.example deploy/.env && vi deploy/.env"
|
||||
@@ -54,6 +92,8 @@ API_PORT="${PORT:-3000}"
|
||||
[ -n "${DB_PASS:-}" ] || die "deploy/.env 中 DB_PASS 未设置"
|
||||
[ -n "${DB_NAME:-}" ] || die "deploy/.env 中 DB_NAME 未设置"
|
||||
|
||||
command -v systemctl >/dev/null 2>&1 || die "未找到 systemctl。本部署依赖 systemd 托管 Node 进程;
|
||||
若目标系统没有 systemd(如容器/WSL1),请改用 SKIP_NGINX=1 手动以进程方式运行,或换一台服务器。"
|
||||
command -v node >/dev/null 2>&1 || die "未找到 node。请安装 Node.js 22 或更高版本。"
|
||||
NODE_BIN="$(command -v node)"
|
||||
NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')"
|
||||
@@ -83,7 +123,7 @@ if [ "$SRC_REAL" = "$APP_REAL" ]; then
|
||||
die "安装目录与源目录相同($APP_REAL)。
|
||||
本脚本会先清空安装目录下的 web-server/ admin/ 再复制,直接在这里执行会删掉源文件。
|
||||
请把发布包解压到别处,或用 APP_DIR=... 指定另一个安装目录:
|
||||
sudo APP_DIR=/opt/opendance bash $0"
|
||||
APP_DIR=/opt/opendance bash $0 (root 身份下执行)"
|
||||
fi
|
||||
case "$APP_REAL/" in
|
||||
"$SRC_REAL"/*)
|
||||
@@ -170,15 +210,15 @@ cd "$APP_DIR/web-server"
|
||||
|
||||
log "安装运行期依赖(仅生产依赖,可能需要 1-3 分钟…)"
|
||||
if [ -f package-lock.json ]; then
|
||||
sudo -u "$SERVICE_USER" npm ci --omit=dev --no-audit --no-fund --loglevel=error
|
||||
as_service_user npm ci --omit=dev --no-audit --no-fund --loglevel=error
|
||||
else
|
||||
sudo -u "$SERVICE_USER" npm install --omit=dev --no-audit --no-fund --loglevel=error
|
||||
as_service_user npm install --omit=dev --no-audit --no-fund --loglevel=error
|
||||
fi
|
||||
|
||||
if [ ! -f dist/main.js ]; then
|
||||
warn "未找到构建产物 dist/main.js,改为在服务器上构建(需要 devDependencies)"
|
||||
sudo -u "$SERVICE_USER" npm install --no-audit --no-fund
|
||||
sudo -u "$SERVICE_USER" npm run build
|
||||
as_service_user npm install --no-audit --no-fund
|
||||
as_service_user npm run build
|
||||
fi
|
||||
[ -f dist/main.js ] || die "构建产物缺失:$APP_DIR/web-server/dist/main.js"
|
||||
[ -f "$APP_DIR/admin/index.html" ] || die "管理端构建产物缺失:$APP_DIR/admin/index.html"
|
||||
@@ -187,7 +227,7 @@ fi
|
||||
log "执行 TypeORM 迁移(不使用 DB_SYNCHRONIZE)"
|
||||
set -a; . "$APP_DIR/deploy/.env"; set +a
|
||||
cd "$APP_DIR/web-server"
|
||||
sudo -u "$SERVICE_USER" env \
|
||||
as_service_user env \
|
||||
"PATH=$(dirname "$NODE_BIN"):/usr/local/bin:/usr/bin:/bin" \
|
||||
"DB_HOST=${DB_HOST}" "DB_PORT=${DB_PORT:-3306}" "DB_USER=${DB_USER}" \
|
||||
"DB_PASS=${DB_PASS}" "DB_NAME=${DB_NAME}" "DB_LOGGING=${DB_LOGGING:-false}" \
|
||||
@@ -210,7 +250,7 @@ systemctl restart opendance-api
|
||||
log "等待 API 就绪…"
|
||||
READY=0
|
||||
for _ in $(seq 1 30); do
|
||||
if curl -fsS -m 3 "http://${API_HOST}:${API_PORT}/health" >/dev/null 2>&1; then READY=1; break; fi
|
||||
if http_ok "http://${API_HOST}:${API_PORT}/health"; then READY=1; break; fi
|
||||
sleep 1
|
||||
done
|
||||
if [ "$READY" -ne 1 ]; then
|
||||
@@ -218,7 +258,7 @@ if [ "$READY" -ne 1 ]; then
|
||||
journalctl -u opendance-api -n 40 --no-pager || true
|
||||
die "API 启动失败"
|
||||
fi
|
||||
log "API 已就绪:$(curl -fsS -m 5 "http://${API_HOST}:${API_PORT}/health" | head -c 200)"
|
||||
log "API 已就绪:$(http_get "http://${API_HOST}:${API_PORT}/health" | head -c 200)"
|
||||
|
||||
# ---------- 5. nginx ----------
|
||||
if [ "${SKIP_NGINX:-0}" = "1" ]; then
|
||||
|
||||
+5
-4
@@ -6,8 +6,8 @@
|
||||
# 数据库从来不由本脚本管理,永不删除。
|
||||
#
|
||||
# 用法:
|
||||
# sudo bash deploy/uninstall.sh # 停服务、禁用站点,保留数据
|
||||
# sudo bash deploy/uninstall.sh --purge # 同时删除程序目录与上传文件
|
||||
# bash deploy/uninstall.sh # 停服务、禁用站点,保留数据(需 root)
|
||||
# bash deploy/uninstall.sh --purge # 同时删除程序目录与上传文件
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
@@ -21,7 +21,8 @@ log() { printf '\033[1;34m[uninstall]\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m[error]\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "需要 root 权限:sudo bash deploy/uninstall.sh"
|
||||
[ "$(id -u)" -eq 0 ] || die "需要 root 权限。请以 root 身份执行,例如:
|
||||
su -c 'bash deploy/uninstall.sh' 或 sudo bash deploy/uninstall.sh"
|
||||
|
||||
log "停止并禁用 opendance-api 服务"
|
||||
systemctl stop opendance-api 2>/dev/null || true
|
||||
@@ -47,6 +48,6 @@ else
|
||||
log "完成。已保留:"
|
||||
echo " 程序目录:$APP_DIR"
|
||||
echo " 上传目录:$STORAGE_DIR"
|
||||
echo " 如需一并删除:sudo bash deploy/uninstall.sh --purge"
|
||||
echo " 如需一并删除(root 身份):bash deploy/uninstall.sh --purge"
|
||||
fi
|
||||
echo " 数据库:始终由部署方自行管理,本脚本不做任何改动"
|
||||
|
||||
Reference in New Issue
Block a user