Python中如何保持SSH连接持久化复用以执行多条命令并获取输出
解决方案
核心思路是直接将SSH连接复用的配置项通过命令行-o参数传递,无需修改系统ssh/config文件,效果和修改配置完全一致。
实现代码
封装成可自主控制生命周期的连接类,支持上下文管理器自动管理连接:
import subprocess import os import tempfile class PersistentSSH: def __init__(self, host, control_persist="10m"): self.host = host # 生成唯一socket路径,避免多进程/多连接冲突 self.socket_path = os.path.join(tempfile.gettempdir(), f"ssh_socket_{os.getpid()}_{hash(host)}") # control_persist指定空闲连接保留时长,可设为yes永久保留、no立即关闭、或如30s/1h等时长 self.control_persist = control_persist def connect(self): """启动后台SSH主连接,仅建立通道不执行命令""" subprocess.run( [ "ssh", "-fN", # -f 后台运行,-N 不执行远程命令 "-o", "ControlMaster=yes", "-o", f"ControlPersist={self.control_persist}", "-o", f"ControlPath={self.socket_path}", self.host ], check=True, capture_output=True, text=True ) def run_command(self, command): """复用已有连接执行命令,返回命令输出""" result = subprocess.run( [ "ssh", "-o", f"ControlPath={self.socket_path}", self.host, command ], check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) return result.stdout def close(self): """主动关闭主连接,清理socket文件""" subprocess.run( ["ssh", "-o", f"ControlPath={self.socket_path}", self.host, "-O", "exit"], capture_output=True ) if os.path.exists(self.socket_path): os.unlink(self.socket_path) # 支持with上下文管理器用法,自动处理连接创建和销毁 def __enter__(self): self.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): self.close()
调用示例
替换原有逻辑的改造非常小,只需将连接实例传入原有方法即可:
def show_one(ssh_conn): return ssh_conn.run_command('cat file1') def show_two(ssh_conn): return ssh_conn.run_command('cat file2') def run(): with PersistentSSH(host="SERVER") as ssh: one = show_one(ssh) print(one) two = show_two(ssh) print(two)
额外说明
- 所有SSH原生参数都可以正常使用,比如需要指定端口、密钥、用户名时,既可以把host写成
user@your_host -p 2222,也可以在ssh命令参数列表中添加-i /path/to/key、-p 2222等参数。 - 可完全自主控制连接生命周期:如果不想用上下文管理器,也可以手动调用
connect()建立连接、多次调用run_command()执行命令、最后调用close()销毁连接,符合显式控制流程的需求。
内容的提问来源于stack exchange,提问作者Asara
相关产品推荐
相关产品推荐

