mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 10:10:43 +00:00
上一个提交把仓库里的服务器 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 三个产物扫描干净
提交前泄漏闸门通过
113 lines
4.3 KiB
Python
113 lines
4.3 KiB
Python
# -*- 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())
|