You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:15:03