#!/bin/bash # 修 watchdog 的重启死循环(这是我上一版改过头造成的) # # 现象(watchdog 日志): # [10:31:57] 只剩 1 条连接 -> 重启隧道 # [10:32:22] 重启完 # [10:32:24] 又只剩 1 条 -> 距上次才 27 秒,先不重启 # [10:32:47] 距上次 50 秒 -> 又重启 # ... 每 50 秒一次,永远不消停 # # 根因: # 隧道在**质量差的 4G 上重建 4 条连接要 30~60 秒**。 # 而我上一版把 MIN_RESTART_GAP 设成 45 秒, # 并且"公网不通 + 连接数<=1"就立刻重启 —— # 结果每次隧道还没把连接建齐,就被下一次重启打断, # **永远停在"只剩 1 条"的状态**。 # # 等于我自己制造了不稳定。 # # 修法: # 1. 重启后给**宽限期**(GRACE=150 秒):这段时间内绝不重启, # 让 cloudflared 专心把连接建齐。 # 2. MIN_RESTART_GAP 从 45 提到 150 秒(和宽限期一致)。 # 3. "立刻重启"的判定加一条:距上次重启必须超过宽限期。 # 确认故障还是立刻重启,但**不能在上次重启还没缓过来的时候**。 set -u echo "════════ 1. 先停掉 watchdog,别一边改一边被它重启 ════════" systemctl stop lanremote-watchdog.timer 2>&1 | sed 's/^/ /' echo " timer: $(systemctl is-active lanremote-watchdog.timer)" echo echo "════════ 2. 让隧道安静地重建一次(别再打断它)════════" systemctl restart lanremote-tunnel echo " 已重启,等它把连接建齐…" for i in $(seq 1 24); do sleep 10 n=$(curl -s --max-time 4 http://127.0.0.1:20241/metrics 2>/dev/null \ | grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}') pub=$(curl -s -o /dev/null -w '%{http_code}' --max-time 8 \ -H 'User-Agent: LanRemote/1.4.0' https://relay.xxmxxs.top/v1/health 2>/dev/null) echo " ${i}0s: 连接 ${n:-?} 公网 $pub" [ "$n" = "4" ] && [ "$pub" = "200" ] && { echo " ✓ 已经建齐且公网通"; break; } done echo echo "════════ 3. 写入修好的 watchdog ════════" # 只在几处关键参数上打补丁,其余逻辑不动 python3 - <<'PY' from pathlib import Path path = Path("/root/lanremote-relay/watchdog.sh") text = path.read_text(encoding="utf-8") # 间隔 45 -> 150 text = text.replace( "MIN_RESTART_GAP=45", "# 两次重启至少隔这么久。\n" "# 150 秒不是拍脑袋:隧道在差的 4G 上重建 4 条连接要 30~60 秒,\n" "# 原来设 45 秒会导致**隧道还没建齐就被下一次重启打断**,\n" "# 永远停在只剩 1 条连接的状态(实测死循环,每 50 秒重启一次)。\n" "# 给足宽限期,让它有机会稳定下来。\n" "MIN_RESTART_GAP=150\n" "GRACE=150") # "确认故障立刻重启" 加上宽限期判断 old = '''if [ "$DEGRADED" = "1" ]; then restart_tunnel "公网不通且只剩 ${CONNS} 条隧道连接(确认故障,立即重启)" fi''' new = '''if [ "$DEGRADED" = "1" ]; then # 宽限期内不重启 —— 让上一次重启有机会把连接建齐。 # (不加这条会死循环:隧道还没建齐就被再次打断。) LAST_R=$(cat "$LAST_RESTART_FILE" 2>/dev/null || echo 0) SINCE=$(( $(date +%s) - LAST_R )) if [ "$SINCE" -lt "$GRACE" ]; then log "公网不通且只剩 ${CONNS} 条连接,但距上次重启才 ${SINCE} 秒(宽限 ${GRACE} 秒)—— 先让它建完" else restart_tunnel "公网不通且只剩 ${CONNS} 条隧道连接(确认故障,立即重启)" fi fi''' if old in text: text = text.replace(old, new, 1) print(" 已加宽限期判断") else: print(" [警告] 找不到'立即重启'那段,没改") path.write_text(text, encoding="utf-8", newline="\n") print(" 参数: MIN_RESTART_GAP=150 GRACE=150") PY echo echo " 语法检查: $(bash -n /root/lanremote-relay/watchdog.sh 2>&1 && echo OK || echo 失败)" grep -E '^MIN_RESTART_GAP|^GRACE|^THRESHOLD' /root/lanremote-relay/watchdog.sh | sed 's/^/ /' echo echo "════════ 4. 重新开 watchdog ════════" systemctl start lanremote-watchdog.timer echo " timer: $(systemctl is-active lanremote-watchdog.timer)" echo echo "════════ 5. 公网连测 15 次 ════════" ok=0 for i in $(seq 1 15); do c=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 \ -H 'User-Agent: LanRemote/1.4.0' https://relay.xxmxxs.top/) [ "$c" = "200" ] && ok=$((ok+1)) printf " %2d: %s\n" "$i" "$c" sleep 2 done echo " 可用 $ok/15"