Python调用subprocess执行SSH时如何保持会话常驻以运行后续命令
解决方案
问题根因
你当前的代码存在两个核心问题导致SSH会话自动退出:
- 你调用SSH时仅传入了单条执行命令,SSH默认执行完指定命令后就会主动断开连接
communicate()方法会等待SSH子进程完全终止后才返回,执行完配置加载逻辑后SSH进程已经退出,自然无法复用会话
推荐方案:使用Paramiko库维护持久SSH会话
Paramiko是Python生态专门用于SSH连接管理的第三方库,原生支持长会话保持,自动处理输入输出流阻塞问题,对新手更友好。
步骤1:安装库
pip install paramiko
步骤2:代码示例
import paramiko # 初始化SSH客户端 ssh = paramiko.SSHClient() # 自动添加主机密钥(生产环境建议关闭,手动配置known_hosts) ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器,按实际情况修改端口、密码/密钥配置 ssh.connect(hostname='xyz', username='abc', port=22, password='你的密码') # 加载配置文件,等待执行完成 stdin, stdout, stderr = ssh.exec_command('source ./profile') # 捕获输出和错误,确认加载成功 load_output = stdout.read().decode() load_error = stderr.read().decode() print("配置加载输出:", load_output) if load_error: print("配置加载报错:", load_error) # 后续可以反复调用exec_command执行其他命令,会话保持开启 # 示例:执行其他命令 stdin, stdout, stderr = ssh.exec_command('echo $CUSTOM_ENV') print("自定义环境变量:", stdout.read().decode()) # 所有操作完成后再关闭连接 ssh.close()
注意:如果需要保留配置加载的环境变量供后续命令使用,建议把后续命令和source操作合并执行,比如
exec_command('source ./profile && 你的其他命令'),或者使用invoke_shell()获取交互式shell实例,环境变量会在整个shell生命周期内保留。
备选方案:subprocess手动维护会话
如果你不想引入第三方依赖,也可以手动维护subprocess的标准流来保持SSH会话,但是需要自行处理缓冲区阻塞问题,稳定性较差:
import subprocess import time # 启动SSH交互式会话,不指定执行命令 p = subprocess.Popen( ['ssh', 'abc@xyz'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1 ) # 发送加载配置命令,注意加换行符模拟回车 p.stdin.write('./profile\n') p.stdin.flush() # 等待配置加载完成(按实际加载时长调整等待时间) time.sleep(90) # 后续发送其他命令 p.stdin.write('你要执行的其他命令\n') p.stdin.flush() # 读取输出逻辑需要自行实现,避免缓冲区满导致进程卡死 # 所有操作完成后关闭会话 p.stdin.write('exit\n') p.communicate()
内容的提问来源于stack exchange,提问作者sonha
相关产品推荐
相关产品推荐

