#!/usr/bin/env bash set -Eeuo pipefail PROJECT_DIR="${AMEIBA_PROJECT_DIR:-/var/www/ameiba-cn-new}" BRANCH="${AMEIBA_BRANCH:-main}" BACKUP_DIR="${AMEIBA_BACKUP_DIR:-/var/backups/ameiba-cms}" CMS_ENV_FILE="$PROJECT_DIR/cms/server/.env" LOCK_FILE="/var/lock/ameiba-update.lock" log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" } fail() { log "失败:$*" exit 1 } command -v git >/dev/null 2>&1 || fail '未安装 git' command -v npm >/dev/null 2>&1 || fail '未安装 npm' command -v pm2 >/dev/null 2>&1 || fail '未安装 pm2' command -v mysqldump >/dev/null 2>&1 || fail '未安装 mysqldump' command -v curl >/dev/null 2>&1 || fail '未安装 curl' exec 9>"$LOCK_FILE" flock -n 9 || fail '已有更新任务正在运行' [[ -d "$PROJECT_DIR/.git" ]] || fail "项目目录不是 Git 仓库:$PROJECT_DIR" [[ -f "$CMS_ENV_FILE" ]] || fail "CMS 环境变量文件不存在:$CMS_ENV_FILE" cd "$PROJECT_DIR" if ! git diff --quiet || ! git diff --cached --quiet; then fail '服务器存在未提交的受版本控制文件修改,请先处理后再更新' fi log '备份 MySQL 数据库' set -a # shellcheck disable=SC1090 source "$CMS_ENV_FILE" set +a : "${DB_HOST:?DB_HOST 未配置}" : "${DB_PORT:?DB_PORT 未配置}" : "${DB_USER:?DB_USER 未配置}" : "${DB_PASSWORD:?DB_PASSWORD 未配置}" : "${DB_NAME:?DB_NAME 未配置}" install -d -m 700 "$BACKUP_DIR" umask 077 BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_$(date '+%Y%m%d_%H%M%S').sql.gz" MYSQL_PWD="$DB_PASSWORD" mysqldump \ --single-transaction \ --quick \ --host="$DB_HOST" \ --port="$DB_PORT" \ --user="$DB_USER" \ "$DB_NAME" | gzip -c > "$BACKUP_FILE" [[ -s "$BACKUP_FILE" ]] || fail '数据库备份文件为空' log "数据库已备份:$BACKUP_FILE" OLD_COMMIT="$(git rev-parse --short HEAD)" log "从 origin/$BRANCH 拉取代码(当前 $OLD_COMMIT)" git fetch origin "$BRANCH" git pull --ff-only origin "$BRANCH" log '安装前台依赖并构建' npm ci npm run build log '安装 CMS 后端生产依赖' ( cd "$PROJECT_DIR/cms/server" npm ci --omit=dev ) log '构建 CMS 管理后台' ( cd "$PROJECT_DIR/cms/admin" npm ci npm run build ) log '重启 CMS 服务并保存 PM2 进程清单' pm2 restart ameba-cms --update-env pm2 save log '执行服务健康检查' curl --fail --silent --show-error --max-time 15 http://127.0.0.1:13001/health >/dev/null curl --fail --silent --show-error --max-time 20 https://www.ameiba.cn/ >/dev/null NEW_COMMIT="$(git rev-parse --short HEAD)" log "更新完成:$OLD_COMMIT -> $NEW_COMMIT"