- 深度扫描从 server_name 行起算须以 depth=1 为初值(server{ 开栏在
该行之前;0 起算在下一行即误判闭合,块切片只剩一行导致 location /
永不匹配——Phase 0 artalk 插入带同款 bug 但恰好落在块顶部而无害)
- STAGING 写死 /home/wait4x 绝对路径(sudo 下 /home/wait4x=/root,计划行
曾显示 /root/docker_apps/...)
验证: 只读模拟 start=94 end=128(真实闭合行),regex 命中,块内
artalk/halo 双 location 齐全;用户首跑在断言处安全中止(写入
前拦截),nginx 配置未受影响
Spec: none (上线脚本热修复,Phase 4 归档后用户执行面缺陷)
Co-authored-by: GLM-5.3
57 lines
2.7 KiB
Bash
Executable File
57 lines
2.7 KiB
Bash
Executable File
#!/bin/bash
|
||
# 上线切换脚本(Phase 4 T5):wait4x.online 从 Halo(18090) 切到静态 staging 目录。
|
||
# 红线:默认 --dry-run 只打印;真实执行必须 root 显式跑(nginx 属 root 域)。
|
||
# 回滚:rollback.sh(同目录,反向切换,同样 dry-run 默认)。
|
||
set -eu
|
||
DRY=1
|
||
[ "${1:-}" = "--exec" ] && DRY=0
|
||
NGINX_DEFAULT=/etc/nginx/sites-available/default
|
||
# sudo 下 $HOME=/root:路径必须写死用户绝对路径,不能用 $HOME
|
||
STAGING="/home/wait4x/docker_apps/blog/www-staging"
|
||
TS=$(date +%Y%m%d-%H%M%S)
|
||
|
||
# 目标:wait4x.online server 块内 location / 的 proxy_pass 换为静态 root。
|
||
# 静态块特性:try_files + URI 归一化尾斜杠(Astro 目录式路由),保留既有 proxy 头段不做它用。
|
||
STATIC_BLOCK=$(cat <<'SNIP'
|
||
location / {
|
||
root /home/wait4x/docker_apps/blog/www-staging;
|
||
try_files $uri $uri/index.html =404;
|
||
}
|
||
SNIP
|
||
)
|
||
|
||
echo "== 上线切换计划 =="
|
||
echo " 备份: $NGINX_DEFAULT -> default.bak-launch-$TS"
|
||
echo " 切换: wait4x.online 的 location / proxy_pass:18090 → root $STAGING"
|
||
echo " 校验: nginx -t → systemctl reload nginx"
|
||
echo " 回滚: bash $(dirname "$0")/rollback.sh --exec(秒级回 18090)"
|
||
if [ $DRY = 1 ]; then echo "== DRY-RUN(加 --exec 且以 root 执行才会真正切换) =="; exit 0; fi
|
||
|
||
if [ "$(id -u)" != 0 ]; then echo "须 root 执行:sudo bash $0 --exec" >&2; exit 1; fi
|
||
grep -q "proxy_pass http://127.0.0.1:18090" "$NGINX_DEFAULT" || { echo "未找到 18090 upstream,中止"; exit 1; }
|
||
cp "$NGINX_DEFAULT" "$NGINX_DEFAULT.bak-launch-$TS"
|
||
python3 - "$NGINX_DEFAULT" <<'PY'
|
||
import re, sys
|
||
path = sys.argv[1]
|
||
s = open(path, encoding="utf-8").read()
|
||
lines = s.splitlines(keepends=True)
|
||
start = next(i for i, l in enumerate(lines) if "server_name wait4x.online;" in l)
|
||
# server{ 开栏在 server_name 之前——从这行起算时已身处一层花括号内,
|
||
# 深度须从 1 起算(0 起算会在下一行误判块闭合,切片只剩一行)
|
||
depth = 1
|
||
for i in range(start, len(lines)):
|
||
depth += lines[i].count("{") - lines[i].count("}")
|
||
if i > start and depth == 0:
|
||
end = i
|
||
break
|
||
block = "".join(lines[start:end])
|
||
new_block = re.sub(r"location / \{.*?\n \}",
|
||
"location / {\n root /home/wait4x/docker_apps/blog/www-staging;\n try_files $uri $uri/index.html =404;\n }",
|
||
block, count=1, flags=re.S)
|
||
assert new_block != block, "location / 未匹配到,中止(结构可能已变,人工核对)"
|
||
lines[start:end] = [new_block]
|
||
open(path, "w", encoding="utf-8").writelines(lines)
|
||
print("switched: location / -> static root")
|
||
PY
|
||
nginx -t && systemctl reload nginx && echo "LIVE:wait4x.online 现服务静态站(回滚:sudo bash $(dirname "$0")/rollback.sh --exec)"
|