Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Can';t关闭使用Popen打开的SSH连接_Python_Python 3.x_Ssh - Fatal编程技术网

Python Can';t关闭使用Popen打开的SSH连接

Python Can';t关闭使用Popen打开的SSH连接,python,python-3.x,ssh,Python,Python 3.x,Ssh,我创建了一个类方法(仅在Linux上运行),它通过SSH向远程计算机发送命令列表,并使用subprocess.Popen返回输出: def remoteConnection(self, list_of_remote_commands): ssh = subprocess.Popen(["ssh", self.ssh_connection_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PI

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

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
虽然我还在学习子流程模块,但我读了很多关于Popen的书,没有人提到过关闭它(,),所以我认为这不是问题

然而,当在ipython中测试函数外部时,我注意到变量
ssh
似乎仍然处于活动状态。我试图关闭ssh.stdin、ssh.stdout和ssh.stderr,甚至是ssh.close()、ssh.terminate()和ssh.kill(),但似乎没有任何东西可以关闭它。我想也许这无关紧要,但我的函数会在几个月甚至几年内被多次调用,所以我不希望每次运行它时都产生一个新的进程,否则我会很快耗尽我的最大进程限制。因此,我使用ssh.pid来查找pid,并使用
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
解决了一个类似的问题,但甚至:

ssh = subprocess.Popen(["ssh", "-T",  self.ssh_connection_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True, bufsize=0)
没用


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

在您的情况下,您在这里遇到了死锁:

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()
然后


我可以补充一点,在特定的ssh情况下,使用paramiko模块更好()并且避免完全使用
子流程。

ssh.communicate
命令抛出错误:
AttributeError:'list'对象没有属性'encode'
也许您的意思是:
command\u input=“\n”。join(远程命令列表)+“\n”
?打开与
popen
ssh
连接听起来是一种不好的做法,您是否研究过
ssh
paramiko
output_dict = {'stdin': list_of_commands, 'stdout': output.splitlines(), 'stderr': error.splitlines()}