繁体   English   中英

Python子进程.Popen管道IO意外阻塞

[英]Python subprocess.Popen pipe IO blocking unexpectedly

我正在尝试使用subprocess.Popen来控制ssh进程并通过管道与之交互,如下所示:

p=subprocess.Popen(['ssh','-tt','LOGIN@HOSTNAME'], stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                    universal_newlines=True)

while True:
    (out_stdout,out_stderr)=p.communicate(timeout=10)
    if out_stderr:
        print(out_stderr)
    if not out_stdout:
        raise EOFError
    print(out_stdout)

如果没有ssh的“ -tt”选项,这可以正常工作。 但是,如果没有分配伪tty,我需要在ssh的远程与之交互的程序会中断,因此我不得不使用它。

这似乎是要进行p.communicate的读取,然后无限期地阻塞(或直到超时),即使输入可用。

我已使用较低级别的io.read,select.select等调用来重写此代码,以避免通过Popen.communicate。 Select实际上会返回准备好的文件描述符,但是随后对该文件描述符的io.read也将阻塞。 如果我禁用“通用换行符”并在Popen调用中将其设置为“ bufsize = 0”,则可以正常工作,但是我不得不自己进行二进制/ Unicode转换和行尾处理。

值得一提的是,在p.communicate版本中禁用Universal_newlines也会无限期地进行阻止,因此不仅如此。

关于如何使行缓冲输入在这里正常工作而不必重新实现所有功能的任何建议?

子流程和SSH二进制文件有一些库替代方案更适合于此类任务。

并行ssh

from pssh.pssh2_client import ParalellSSHClient
client = ParallelSSHClient(['HOSTNAME'], user='LOGIN')
output = client.run_command('echo', use_pty=True)

for host, host_output in output.items():
    for line in host_output.stdout:
        print(line)

echo替换为您需要运行的命令,如果不需要任何命令,请保留原样。 这些库要求将某些内容作为命令传递,即使远程端自动执行某些操作。

另请参见同一项目的单个主机SSHClient的文档。

根据文档,行解析和编码均由跨平台的库处理。

还有其他一些工具,例如paramiko和ssh2-python,它们是较低的级别,并且需要与以上等效的更多代码-示例请参见各自的主页。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM