From 41bf110e22dbb27171fa2a4c2eb8f9bccd14402c Mon Sep 17 00:00:00 2001 From: xmz7891 Date: Wed, 7 Oct 2026 20:29:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=20devssh=EF=BC=9A=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E4=BA=86=20HOST=5FFALLBACKS=20=E5=8D=B4=E4=BB=8E=E6=9D=A5?= =?UTF-8?q?=E6=B2=A1=E7=94=A8=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 随身 WiFi 跟着教室网络走,地址会在 192.168.2.156 和 192.168.10.105 之间变。devssh.py 里明明定义了 HOST_FALLBACKS, 但 run / upload / download 三个函数**全都直接用 HOST** —— 于是设备一换网段就全部连不上,而且报的是连接超时, 看起来像设备挂了。 现在改成按候选列表顺序试: 环境变量 YKXMZ_DEV_HOST 优先 -> 192.168.2.156(当前) -> 192.168.10.105(换网前用过) 并记住上次通的那个,后续调用不用每次从头试。 连上时打一行 `[devssh] 连上 x.x.x.x`,免得以后又搞不清连的是哪台。 还加了 `--probe` 子命令,一句话看现在哪个地址能用: python _build/devssh.py --probe 实测:192.168.2.156 通、192.168.10.105 不通,自动选中前者。 --- _build/_cmsg8.txt | 20 ++++++++ _build/devssh.py | 116 ++++++++++++++++++++++++++++++++---------- _build/rp_pc_long.tsv | 21 ++++++++ _build/snap_rp2.sh | 39 ++++++++++++++ 4 files changed, 169 insertions(+), 27 deletions(-) create mode 100644 _build/_cmsg8.txt create mode 100644 _build/snap_rp2.sh diff --git a/_build/_cmsg8.txt b/_build/_cmsg8.txt new file mode 100644 index 0000000..3514514 --- /dev/null +++ b/_build/_cmsg8.txt @@ -0,0 +1,20 @@ +修 devssh:定义了 HOST_FALLBACKS 却从来没用过 + +随身 WiFi 跟着教室网络走,地址会在 192.168.2.156 和 +192.168.10.105 之间变。devssh.py 里明明定义了 HOST_FALLBACKS, +但 run / upload / download 三个函数**全都直接用 HOST** —— +于是设备一换网段就全部连不上,而且报的是连接超时, +看起来像设备挂了。 + +现在改成按候选列表顺序试: + 环境变量 YKXMZ_DEV_HOST 优先 + -> 192.168.2.156(当前) + -> 192.168.10.105(换网前用过) +并记住上次通的那个,后续调用不用每次从头试。 +连上时打一行 `[devssh] 连上 x.x.x.x`,免得以后又搞不清连的是哪台。 + +还加了 `--probe` 子命令,一句话看现在哪个地址能用: + + python _build/devssh.py --probe + +实测:192.168.2.156 通、192.168.10.105 不通,自动选中前者。 diff --git a/_build/devssh.py b/_build/devssh.py index 90b4027..4e74896 100644 --- a/_build/devssh.py +++ b/_build/devssh.py @@ -4,38 +4,100 @@ 用法: python _build/devssh.py "命令" # 跑一条命令 python _build/devssh.py --script 文件 # 跑一段脚本 + +== 地址会自动试 == + +这台设备跟着教室网络走,地址会变: + 192.168.2.156 <-> 192.168.10.105 +所以这里**按顺序试多个地址**,谁先连通就用谁,不用改代码。 + +想强制指定就用环境变量: + $env:YKXMZ_DEV_HOST = "192.168.10.105" + +⚠ 以前的坑:定义了 HOST_FALLBACKS 但**三个函数都直接用 HOST**, + 那个常量根本没被用过。于是设备一换网段就全部连不上, + 而且报的是「Connection refused / timed out」,看起来像设备挂了。 """ from __future__ import annotations +import os import sys import time from pathlib import Path import paramiko -# 随身 WiFi(Debian)的地址。 -# -# 这台设备跟着教室网络走,地址会变: -# 192.168.2.156 -> 192.168.10.105(换网络了) -# 所以优先读环境变量 YKXMZ_DEV_HOST,没有才用下面的默认值。 -# 换网络时不用改代码: -# $env:YKXMZ_DEV_HOST = "192.168.10.105" -import os - -HOST = os.environ.get("YKXMZ_DEV_HOST", "192.168.10.105") USER = "root" PASSWORD = os.environ.get("YKXMZ_DEV_PASS", "1313144") -# 旧地址留一份,方便回退或同时探测 -HOST_FALLBACKS = ("192.168.10.105", "192.168.2.156") +# 候选地址,按顺序试。 +# 环境变量优先(想锁定时用),然后是最近见过的两个地址。 +_CANDIDATES: list[str] = [] + + +def _build_candidates() -> list[str]: + out = [] + env_host = (os.environ.get("YKXMZ_DEV_HOST") or "").strip() + if env_host: + out.append(env_host) + for host in ("192.168.2.156", # 当前地址 + "192.168.10.105"): # 换网络前用过 + if host not in out: + out.append(host) + return out + + +CANDIDATES = _build_candidates() +HOST = CANDIDATES[0] # 兼容老代码:默认取第一个 +HOST_FALLBACKS = tuple(CANDIDATES[1:]) + +# 记住这次连通的是哪个,后续调用不用每次从头试 +_CONNECTED: str | None = None + + +def _connect(timeout: int = 15): + """按候选顺序连,返回 (client, host)。全都不通才抛异常。""" + global _CONNECTED + order = list(CANDIDATES) + if _CONNECTED and _CONNECTED in order: + # 上次通的那个排最前,省一次失败尝试 + order.remove(_CONNECTED) + order.insert(0, _CONNECTED) + + errors = [] + for host in order: + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + client.connect(host, username=USER, password=PASSWORD, + timeout=timeout, banner_timeout=20, + auth_timeout=20, look_for_keys=False, + allow_agent=False) + if _CONNECTED != host: + print(f" [devssh] 连上 {host}") + _CONNECTED = host + return client, host + except Exception as exc: # noqa: BLE001 + errors.append(f"{host}: {type(exc).__name__} {exc}") + try: + client.close() + except Exception: # noqa: BLE001 + pass + raise RuntimeError("所有候选地址都连不上:\n " + "\n ".join(errors)) + + +def probe() -> str | None: + """探一下现在哪个地址能用(不抛异常)。""" + try: + client, host = _connect(timeout=8) + client.close() + return host + except Exception: # noqa: BLE001 + return None def run(command: str, timeout: int = 600, quiet: bool = False) -> tuple: - client = paramiko.SSHClient() - client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - client.connect(HOST, username=USER, password=PASSWORD, timeout=15, - banner_timeout=20, auth_timeout=20, - look_for_keys=False, allow_agent=False) + client, _host = _connect() try: _stdin, stdout, stderr = client.exec_command(command, timeout=timeout) out = stdout.read().decode("utf-8", "replace") @@ -52,10 +114,7 @@ def run(command: str, timeout: int = 600, quiet: bool = False) -> tuple: def upload(local: str, remote: str, mode: int = 0o644) -> None: - client = paramiko.SSHClient() - client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - client.connect(HOST, username=USER, password=PASSWORD, timeout=15, - look_for_keys=False, allow_agent=False) + client, _host = _connect() try: sftp = client.open_sftp() sftp.put(local, remote) @@ -67,10 +126,7 @@ def upload(local: str, remote: str, mode: int = 0o644) -> None: def download(remote: str, local: str) -> None: - client = paramiko.SSHClient() - client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - client.connect(HOST, username=USER, password=PASSWORD, timeout=15, - look_for_keys=False, allow_agent=False) + client, _host = _connect() try: sftp = client.open_sftp() sftp.get(remote, local) @@ -83,13 +139,19 @@ def download(remote: str, local: str) -> None: if __name__ == "__main__": if len(sys.argv) < 2: print(__doc__) + print(" 候选地址: %s" % ", ".join(CANDIDATES)) + print(" 现在能连的: %s" % (probe() or "(一个都不通)")) sys.exit(1) if sys.argv[1] == "--script": run(Path(sys.argv[2]).read_text(encoding="utf-8"), timeout=600) + elif sys.argv[1] == "--probe": + got = probe() + print(" 能连的地址: %s" % (got or "(一个都不通)")) + sys.exit(0 if got else 1) else: args = sys.argv[1:] timeout = 600 - if args and args[0] == '--timeout': + if args and args[0] == "--timeout": timeout = int(args[1]) args = args[2:] - run(" ".join(args), timeout=timeout) + sys.exit(run(" ".join(args), timeout=timeout)[0]) diff --git a/_build/rp_pc_long.tsv b/_build/rp_pc_long.tsv index 436bc3f..67b1adf 100644 --- a/_build/rp_pc_long.tsv +++ b/_build/rp_pc_long.tsv @@ -309,3 +309,24 @@ time code ms 2026-10-07 19:00:44 200 1199 2026-10-07 19:01:00 200 1335 2026-10-07 19:01:17 200 1437 +2026-10-07 19:01:33 200 1430 +2026-10-07 19:01:50 200 1414 +2026-10-07 19:02:06 200 1146 +2026-10-07 19:02:22 200 1079 +2026-10-07 19:02:38 200 1429 +2026-10-07 19:02:54 200 1057 +2026-10-07 19:03:11 200 1479 +2026-10-07 19:03:27 200 1129 +2026-10-07 19:03:44 200 1790 +2026-10-07 19:04:00 200 1420 +2026-10-07 19:04:18 200 2459 +2026-10-07 19:04:34 200 1148 +2026-10-07 19:04:50 200 1420 +2026-10-07 19:05:06 200 1085 +2026-10-07 19:05:23 200 1428 +2026-10-07 19:05:39 200 1017 +2026-10-07 19:05:55 200 1427 +2026-10-07 19:06:11 200 1085 +2026-10-07 19:06:27 200 1139 +2026-10-07 19:06:44 200 1036 +2026-10-07 19:06:59 200 833 diff --git a/_build/snap_rp2.sh b/_build/snap_rp2.sh new file mode 100644 index 0000000..083c132 --- /dev/null +++ b/_build/snap_rp2.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# relay-stability 停了,看它留下了什么 +set -u + +echo " ── 还有没有它的进程 ──" +pgrep -af 'rp_|long2h|ab_long|collapse' 2>/dev/null | head -5 | sed 's/^/ /' || echo " (没有)" + +echo +echo " ── 2 小时长测:最后状态 ──" +if [ -f /root/long2h_health.tsv ]; then + echo " 样本数: $(wc -l < /root/long2h_health.tsv)" + echo " 最后 3 条:" + tail -3 /root/long2h_health.tsv | sed 's/^/ /' +else + echo " (没有文件)" +fi + +echo +echo " ── 配比对照跑了吗 ──" +for s in lanremote-tunnel lanremote-tunnel-h2; do + printf " %-24s %s (%s)\n" "$s" \ + "$(grep -oE -- '--protocol [a-z0-9]+|--ha-connections [0-9]+' \ + "/etc/systemd/system/$s.service" 2>/dev/null | tr '\n' ' ')" \ + "$(systemctl is-active $s 2>/dev/null)" +done +ls -la --time-style=+%H:%M /root/*ab*.tsv /root/*ab*.out /root/*ratio* 2>/dev/null | sed 's/^/ /' || echo " (没有对照的产物)" + +echo +echo " ── 它最后改的脚本(看它做到哪一步)──" +ls -la --time-style=+%H:%M:%S /root/rp_ab_long.sh /root/rp_collapse.py /root/rp_collapse.tsv 2>/dev/null | sed 's/^/ /' + +echo +echo " ── 公网自检 ──" +curl -s --max-time 20 -o /dev/null -w ' HTTP %{http_code} %{time_total}s\n' \ + -H 'User-Agent: LanRemote/1.8.2' https://relay.xxmxxs.top/v1/health + +echo +echo " ── 设备时间 ──" +date '+ %H:%M:%S'