From 2fba6d82f44ca25f9972d35ac20fbba6b1f2cb99 Mon Sep 17 00:00:00 2001 From: aszerW Date: Tue, 12 May 2026 22:40:35 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20SSH=E9=9A=A7=E9=81=93=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=89=8D=E6=B8=85=E7=90=86=E6=AE=8B=E7=95=99=E8=BF=9B=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - 多次运行回测后残留SSH进程干扰代理连接 - yfinance因代理冲突无法获取数据 修复: - SSHTunnelManager添加 _cleanup_old_processes 方法 - 启动新隧道前自动清理同端口残留进程 验证: - 清理后YFinance成功下载纳指、日经、DAX等数据 --- datasource/ssh_tunnel.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/datasource/ssh_tunnel.py b/datasource/ssh_tunnel.py index fb54a61..6ec1e28 100644 --- a/datasource/ssh_tunnel.py +++ b/datasource/ssh_tunnel.py @@ -42,6 +42,25 @@ class SSHTunnelManager: key_path = str(project_root / key_path) self.key_path = key_path + def _cleanup_old_processes(self): + """清理残留的同端口SSH进程""" + try: + # 查找监听同一端口的SSH进程 + result = subprocess.run( + ['pgrep', '-f', f'ssh.*-D.*{self.local_port}'], + capture_output=True, text=True + ) + if result.returncode == 0 and result.stdout.strip(): + pids = result.stdout.strip().split('\n') + for pid in pids: + try: + subprocess.run(['kill', '-9', pid], check=True) + print(f" 清理残留SSH进程: PID {pid}") + except subprocess.CalledProcessError: + pass + except Exception: + pass # pgrep不可用或其他问题,忽略 + def start(self) -> bool: """启动SSH隧道""" if not self.enabled: @@ -51,6 +70,9 @@ class SSHTunnelManager: print("SSH配置不完整,跳过隧道建立") return False + # 先清理残留的同端口SSH进程 + self._cleanup_old_processes() + print(f"建立SSH隧道: {self.host}:{self.port} -> 本地SOCKS5端口 {self.local_port}") cmd = [