无法关闭与Popen打开的SSH连接

时间:2018-04-06 16:28:22

标签: python python-3.x ssh

我创建了一个类方法(这只能在Linux上运行),它通过SSH将命令列表发送到远程计算机,并使用subprocess.Popen返回输出:

<css-placeholder token="{{ placeholder_token }}">

虽然我仍然在掌握子流程模块,但我已经阅读了很多关于Popen的内容,并且没有人提到关闭它(SSH Connection with Python 3.0Proper way to close all files after subprocess Popen and communicate,{{ 3}})所以我认为这不是问题。

然而,当在函数外部的ipython中测试它时,我注意到变量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) # send ssh commands to stdin for command in list_of_remote_commands: ssh.stdin.write(command + "\n") ssh.stdin.close() output_dict = {'stdin': list(ssh.stdin), 'stdout': list(ssh.stdout), 'stderr': list(ssh.stderr)} return output_dict 似乎仍然活跃。我尝试关闭ssh.stdin,ssh.stdout和ssh.stderr甚至ssh.close(),ssh.terminate()和ssh.kill()但似乎没有关闭它。我想也许这并不重要,但我的功能会被召唤好几个月甚至几年,所以我不想让它每次运行都会产生一个新的过程,否则我很快就会去用完了我的最大进程限制。所以我使用ssh.pid查找PID并使用ssh进行查找,即使在完成上述所有操作之后它仍然存在。

我也尝试过:

ps aux | grep PID

而不是:

with subprocess.Popen(["ssh", self.ssh_connection_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True, bufsize=0) as shh:

我还记得在使用ssh = subprocess.Popen(["ssh", self.ssh_connection_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True, bufsize=0) 的同时解决类似的问题但是甚至:

ssh -T

没有工作。

我确定如果需要的话,我会找到关于关闭Popen的内容但是为什么这个过程仍然在我的计算机上打开 - 有人能帮我理解这里发生了什么吗?

1 个答案:

答案 0 :(得分:2)

在你的情况下,你有一个僵局:

output_dict = {'stdin': list(ssh.stdin), 'stdout': list(ssh.stdout), 'stderr': list(ssh.stderr)}

主要是因为list(ssh.stdin)永久阻止:尝试读取进程的标准输入不起作用(因为您将标准输出和错误重定向到不同的管道,所以还存在额外的风险不使用线程来消费它们)

您的意思是使用ssh.communicate,将整个输入作为参数传递。只需:

command_input = "".join(["{}\n".format(x) for x in list_of_remote_commands])
output,error = ssh.communicate(command_input)  # may need .encode() for python 3
return_code = ssh.wait()

然后

output_dict = {'stdin': list_of_commands, 'stdout': output.splitlines(), 'stderr': error.splitlines()}

我可以在特定的ssh情况下添加,使用paramiko模块更好(python paramiko ssh)并避免完全使用subprocess