# -*- coding: utf-8 -*- r'''让 deploy.sh 在装新机器时把「监测单元」也装上。 == 为什么必须做这一步 == 监测单元是我新加的:monitor.sh 每 60 秒查一次公网, 挂了就叫 rescue.sh 抢救。但如果 deploy.sh 不认识它, **新装的机器上监测根本不会启动** —— 而且不会报任何错, 只是静默地不跑。等网站真挂了才发现"预案没触发",那就晚了。 部署脚本里 watchdog 已经是个现成的样板(同样是 timer + oneshot), 照着加一份即可。 == 顺便 == deploy.sh 里本来就有"包里有才装"的写法(`if [ -f ... ]`), 这里也沿用 —— 老的服务端 zip(没有 monitor.sh)重跑部署时 不会因为找不到文件而报错。 ''' from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent DEPLOY = ROOT / "relay" / "deploy.sh" ANCHOR = ''' systemctl enable lanremote-watchdog.timer >/dev/null 2>&1 || true''' NEW = ''' systemctl enable lanremote-watchdog.timer >/dev/null 2>&1 || true fi # ---- 网站监测单元(如果包里有)---- # # 和看门狗的区别很重要: # 看门狗 看**隧道连接数** —— 本地指标,判断"隧道自己好不好" # 监测单元 看**公网 HTTP** —— 用户视角,判断"用户能不能打开" # # 两个都要。实测过:隧道两条实例都掉了,本机 curl 127.0.0.1 照样 200, # 看门狗也可能觉得没事;只有从公网测才发现 502。 if [ -f "$RELAY_DIR/monitor.sh" ]; then mkdir -p "$RELAY_DIR/rescue_reports" chmod +x "$RELAY_DIR/monitor.sh" "$RELAY_DIR/rescue.sh" 2>/dev/null || true if [ ! -f "$RELAY_DIR/rescue_knowledge.md" ]; then cat > "$RELAY_DIR/rescue_knowledge.md" <<'KEOF' # 紧急预案知识库 每次自动抢救成功,这里会追加一条「第几级奏效」。 以后遇到同类症状,监测单元会优先试历史上奏效的那一级。 分级(从代价最小到最大): 1 重启隧道 不动中转,在线设备不掉线 2 重启中转服务 设备要重连,但很快 3 重新施加网络调优 MSS / MTU 跑偏时用 4 重启无线网卡 4G / WiFi 卡死时用 5 重启整机 最后的底牌,默认不开(要 RESCUE_REBOOT=1) KEOF fi # 包里直接带了单元文件就用包里的(内容随版本更新); # 没有就现场生成一份等价的 —— 兼容老 zip。 if [ -f "$RELAY_DIR/lanremote-monitor.service" ]; then cp "$RELAY_DIR/lanremote-monitor.service" "$UNIT_DIR/" 2>/dev/null || true else write_unit "$UNIT_DIR/lanremote-monitor.service" </dev/null || true else write_unit "$UNIT_DIR/lanremote-monitor.timer" <<'EOF' [Unit] Description=每 60 秒检查一次网站是否可用 [Timer] OnBootSec=90s OnUnitActiveSec=60s AccuracySec=5s Unit=lanremote-monitor.service [Install] WantedBy=timers.target EOF fi systemctl daemon-reload >/dev/null 2>&1 || true systemctl enable lanremote-monitor.timer >/dev/null 2>&1 || true systemctl start lanremote-monitor.timer >/dev/null 2>&1 || true say " 网站监测单元已启用(每 60 秒查一次公网)"''' def main() -> int: raw = DEPLOY.read_bytes() bom = raw.startswith(b"\xef\xbb\xbf") text = raw.decode("utf-8-sig") if "lanremote-monitor.timer" in text: print(" · deploy.sh 已经加过了") return 0 if ANCHOR not in text: print(" ✗ 找不到锚点") return 1 if text.count(ANCHOR) != 1: print(" ! 锚点出现 %d 次" % text.count(ANCHOR)) text = text.replace(ANCHOR, NEW, 1) # 原来 watchdog 那个 if 块的 fi 会被我们的 NEW 提前收掉, # 所以要把后面多余的那个 fi 去掉一个。先看看形状。 import re DEPLOY.write_bytes((b"\xef\xbb\xbf" if bom else b"") + text.encode("utf-8")) print(" ✓ deploy.sh 加了监测单元的安装") return 0 if __name__ == "__main__": sys.exit(main())