无法关闭通过Popen打开的SSH连接问题求助
解决SSH连接无法关闭的问题
嘿,我之前也碰到过一模一样的情况!你现在的问题是只关闭了stdin,但SSH进程还在等着会话主动结束,所以一直挂着没退出。试试下面这几个办法,亲测好用:
1. 主动发送退出命令让SSH会话收尾
在所有业务命令发送完之后,额外加一个exit命令,明确告诉SSH客户端可以结束会话了。这样SSH进程会主动关闭连接,不会一直卡在那里等待输入:
def remoteConnection(self, list_of_remote_commands): ssh = subprocess.Popen( ["ssh", self.ssh_connection_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, bufsize=0 ) # 发送所有需要执行的远程命令 for command in list_of_remote_commands: ssh.stdin.write(command + "\n") # 关键步骤:发送exit命令触发SSH会话结束 ssh.stdin.write("exit\n") ssh.stdin.close() # 等待进程完全终止,同时读取输出和错误信息 stdout, stderr = ssh.communicate() return_code = ssh.wait() # 这里可以根据需求处理输出或返回码,比如返回给调用方 return stdout, stderr, return_code
2. 用communicate()替代手动操作stdin(更推荐)
其实subprocess的communicate()方法可以一站式处理输入、输出和进程等待,比手动写stdin更稳妥,还能避免僵尸进程的出现:
def remoteConnection(self, list_of_remote_commands): # 把所有命令拼接成字符串,最后加上exit命令 commands_str = "\n".join(list_of_remote_commands) + "\nexit\n" ssh = subprocess.Popen( ["ssh", self.ssh_connection_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True ) # 一次性发送所有命令,自动等待进程结束并获取输出 stdout, stderr = ssh.communicate(input=commands_str) return_code = ssh.returncode return stdout, stderr, return_code
这个方法会自动帮你处理stdin的关闭,并且确保进程完全终止,不会留下残留的SSH进程。
3. 极端情况:强制终止进程
如果上面的优雅退出方式不管用(比如远程命令卡住了),可以用terminate()或者kill()强制结束进程,但尽量优先用前面的方法,毕竟强制杀进程可能会导致输出不完整:
# 检查进程是否还在运行 if ssh.poll() is None: ssh.terminate() # 先发送SIGTERM尝试优雅终止 # 如果还是没反应,再用kill()发送SIGKILL强制杀死 # ssh.kill()
补充小提示
- Python 3.7及以上版本可以把
universal_newlines=True换成text=True,语义更清晰。 - 如果你的远程命令需要交互(比如输入密码),这种纯stdin的方式可能不够灵活,建议试试
paramiko这类专门的SSH库,功能更强大也更好控制。
内容的提问来源于stack exchange,提问作者ojunk
相关产品推荐
相关产品推荐

