Files
ykxmz/_build/install_lightsail_monitor_v2.py
T
xmz7891 0ad3f648c6 修上一轮清理留下的副作用:占位符把运维脚本弄连不上了
上一个提交把仓库里的服务器 IP 换成了占位符,但**那些脚本本身要用这个 IP
去连服务器** —— 换掉之后它们就跑不起来了。这个提交把取值方式理清楚。

== 取值统一走 _build/lssh.py ==

    YKXMZ_LS_HOST 环境变量
    或 _build/.lightsail_host(一行 IP,已 gitignore)
    都没有就报错,并告诉你怎么设

十个运维脚本改成 `from lssh import ... HOST as LS_HOST`,
公开仓库里一个具体地址都不留。

== 顺带修的两个自己造的 bug ==

  * 用正则往 `from lssh import ...` 后面追加东西时,
    追加到了行尾的 `# noqa: E402` **注释里面** ——
    十处导入全是废的,脚本一跑就 NameError。
    改成先剥掉注释、拼好导入、再把 noqa 加回去。

  * 同一个正则还把 `from lssh import HOST as LS_HOST` 加进了
    **lssh.py 自己**,造成自我导入。

教训:**正则批量改导入语句很危险**(注释、行尾、顺序都能坑到),
这种地方宁可逐个 edit。

== 为什么要重建产物 ==

docs/AFTER-INSTALL.txt 会被打进服务端 zip,而它上一轮改过
(去掉了写死的旧管理员密码)—— 不重打的话发出去的还是旧的。

重打后确认:三个产物里都没有旧密码、没有服务器 IP。

== 验证 ==

    全量回归退出码 0,41 个阶段全 PASS
    603 个 Python 文件语法通过
    ykxmz-agent / server / watch 三个产物扫描干净
    提交前泄漏闸门通过
2026-10-09 00:02:32 +08:00

113 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r'''把本地的 monitor/rescue 脚本装到 Lightsail(第二版:https 版)。
== 为什么单独写一个,而不是继续远端打补丁 ==
前面几轮我一直在用"SSH 过去、用嵌套 heredoc 现场改 monitor.sh"的做法,
结果连续踩了三次:
1. PowerShell 的 `$(...)` 在**本机**被求值(报"systemctl 不是 cmdlet")
2. 引号被吃掉 -> Python 报 unterminated string literal
3. 脚本里的 `%{http_code}` 和 Python 的 `%` 格式化打架
-> "not enough arguments for format string"
根本问题:**远端打补丁这件事本身就脆弱**。
本地写完整文件、整份上传,就没有这些问题 —— 而且改了什么一目了然,
还能进 git 做版本管理。
所以现在改成:relay/monitor-lightsail.sh 和 relay/rescue-lightsail.sh
是**唯一事实来源**,本地编辑 -> 整份上传 -> 重装。
== 本地文件名 vs 远端文件名 ==
本地叫 monitor-lightsail.sh(和那台旧的 monitor.sh 区分开,
免得看混),远端统一叫 monitor.sh / rescue.sh,
因为 systemd unit 和监测脚本里写的是这个名字。
'''
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "_build"))
from lssh import run, upload, HOST as LS_HOST # noqa: E402
RELAY_DIR = "/opt/ykxmz-relay"
# (本地文件, 远端文件名)
PAIRS = [
("relay/monitor-lightsail.sh", "monitor.sh"),
("relay/rescue-lightsail.sh", "rescue.sh"),
]
def main() -> int:
print("=" * 62)
print(" 装 monitor / rescue 到 Lightsail")
print("=" * 62)
print()
print(" ── 1. 上传 ──")
for local_name, remote_name in PAIRS:
local = ROOT / local_name
if not local.is_file():
print(" ✗ 找不到 %s" % local_name)
return 1
upload(str(local), "%s/%s" % (RELAY_DIR, remote_name), mode=0o755)
print()
print(" ── 2. 语法检查 ──")
out = run("cd %s && for f in monitor.sh rescue.sh; do "
"bash -n $f || exit 1; done && echo SH_OK" % RELAY_DIR,
timeout=120, quiet=True)
print(" " + out[1].strip())
print()
print(" ── 3. 重置状态 + 跑一次监测 ──")
out = run("printf 'fails=0\\nlast_rescue=0\\n' > "
"%s/monitor_state.txt; "
"bash %s/monitor.sh; echo ' --- 状态 ---'; "
"cat %s/monitor_state.txt | sed 's/^/ /'; "
"echo ' --- 日志尾 ---'; "
"tail -3 %s/monitor.log | sed 's/^/ /'"
% (RELAY_DIR, RELAY_DIR, RELAY_DIR, RELAY_DIR),
timeout=180, quiet=True)
for ln in out[1].strip().splitlines():
print(ln)
print()
print(" ── 4. 探测各层现在什么状态 ──")
probe = (
'printf " %-36s %s\\n" "PRIMARY https://域名" '
'"$(curl -sL -o /dev/null -w \'%{http_code}\' --max-time 15 '
'https://yk.xxmxxs.top/v1/health)"; '
'printf " %-36s %s\\n" "FALLBACK 127.0.0.1:13245" '
'"$(curl -s -o /dev/null -w \'%{http_code}\' --max-time 8 '
'http://127.0.0.1:13245/v1/health)"; '
'printf " %-36s %s\\n" "nginx :80(301 到 https)" '
'"$(curl -s -o /dev/null -w \'%{http_code}\' --max-time 8 '
'http://127.0.0.1:80/v1/health)"; '
'printf " %-36s %s\\n" "nginx :443(本机带 SNI)" '
'"$(curl -sk -o /dev/null -w \'%{http_code}\' --max-time 8 '
'--resolve yk.xxmxxs.top:443:127.0.0.1 '
'https://yk.xxmxxs.top/v1/health)"; '
'printf " %-36s %s\\n" "公网 443(Lightsail 防火墙)" '
'"$(curl -sk -o /dev/null -w \'%{http_code}\' --max-time 8 '
'https://LS_HOST/v1/health 2>/dev/null || echo 不通)"'
)
out = run(probe, timeout=180, quiet=True)
for ln in out[1].strip().splitlines():
print(ln)
print()
print(" 说明:PRIMARY 现在是 522 —— 因为公网 443 还没开。")
print(" 这不影响 FALLBACK 正常,所以监测**不会**误报成")
print(" '中转挂了';它会把层次标成 edge(问题在边缘层),")
print(" 等 443 开了 PRIMARY 自然就 200 了。")
return 0
if __name__ == "__main__":
sys.exit(main())