diff --git a/deploy/deploy.sh b/deploy/deploy.sh index 51fbc24..53bb1c6 100644 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -115,11 +115,20 @@ if [ -f "$DEPLOY_DIR/.pending-deploy" ]; then 请先确认当前状态(容器/迁移/versions.log)再继续,然后删除该标记或人工处理后重跑。" fi -# 2. source .env(G:PG_PASSWORD/REDIS_PASSWORD 供 pg_dump 备选与探活) +# 2. 提取 .env 中脚本直接需要的标量变量(G:PG_PASSWORD 供 pg_dump)。 +# 绝不 `set -a; source .env`——bash 会把 `KEY=["a","b"]` 按数组语法解析剥掉引号, +# 且 export 进 shell 后 docker compose 插值会优先用 shell 值(优先于 .env 文件), +# 导致迁移容器拿到剥引号的 CORS_ORIGINS(非 JSON)而崩。compose 自身读 .env 文件, +# 能正确拿到带引号的原始值,所以这里只取标量、不 export。 if [ ! -f "$REPO_ROOT/.env" ]; then error "未找到 ${REPO_ROOT}/.env(含密钥,不进 git)。请先在服务器配置。" fi -set -a; source "$REPO_ROOT/.env"; set +a +get_env() { + local var="$1" raw + raw="$(grep -E "^[[:space:]]*(export[[:space:]]+)?${var}[[:space:]]*=" "$REPO_ROOT/.env" | tail -1 | sed -E "s/^[^=]*=//" || true)" + printf -v "$var" '%s' "$raw" +} +get_env PG_PASSWORD # 3. .env 复杂类型预检(fail fast):pydantic-settings 会把 list/dict 类型字段按 JSON 解析, # 写成了逗号列表会在迁移时炸(8-10 事故),这里提前捕获,给出正确写法提示。 @@ -322,6 +331,9 @@ check_single_head auto_rollback() { echo -e "${RED}[✗] 部署部分完成(迁移已跑/容器已切),触发自动回滚${NC}" + # 释放本脚本持有的部署锁(fd 9)再调 rollback.sh——否则 rollback.sh --auto 自身的 + # flock 会被自己占的锁挡住,形成死锁(8-10 实际发生:自动回滚被锁拦下) + exec 9>&- bash "$DEPLOY_DIR/rollback.sh" --auto || warn "自动回滚失败,请人工介入(详见 docs/16 §3 回滚 runbook)" exit 1 }