简体   繁体   English

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

[英]Python subprocess.Popen pipe IO blocking unexpectedly

I am trying to use subprocess.Popen to control an ssh process and interact with it via pipes, like so: 我正在尝试使用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)

This works fine without the '-tt' option to ssh. 如果没有ssh的“ -tt”选项,这可以正常工作。 However the program I need to interact with on the remote side of the ssh breaks if there is no pseudo tty allocated, so I am forced to use it. 但是,如果没有分配伪tty,我需要在ssh的远程与之交互的程序会中断,因此我不得不使用它。

What this seems to do is that the p.communicate reads then block indefinitely (or until timeout), even if input is available. 这似乎是要进行p.communicate的读取,然后无限期地阻塞(或直到超时),即使输入可用。

I have rewritten this using lower level calls to io.read, select.select etc to avoid going through Popen.communicate. 我已使用较低级别的io.read,select.select等调用来重写此代码,以避免通过Popen.communicate。 Select will actually return the file descriptor as ready, but a subsequent io.read to that file descriptor will also block. Select实际上会返回准备好的文件描述符,但是随后对该文件描述符的io.read也将阻塞。 If I disable 'universal newlines' and set 'bufsize=0' in the Popen call it then works fine, but then I am forced to do binary/unicode conversion and line ending processing myself. 如果我禁用“通用换行符”并在Popen调用中将其设置为“ bufsize = 0”,则可以正常工作,但是我不得不自己进行二进制/ Unicode转换和行尾处理。

It's worth saying though, that disabling universal_newlines in the p.communicate version also blocks indefinitely, so its not just that. 值得一提的是,在p.communicate版本中禁用Universal_newlines也会无限期地进行阻止,因此不仅如此。

Any advice on how I can get line buffered input working properly here without having to reimplement everything? 关于如何使行缓冲输入在这里正常工作而不必重新实现所有功能的任何建议?

There are library alternatives to subprocess and the SSH binary that are better suited for such tasks. 子流程和SSH二进制文件有一些库替代方案更适合于此类任务。

parallel-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)

Replace echo with the command you need to run, or leave as-is if no command is required. echo替换为您需要运行的命令,如果不需要任何命令,请保留原样。 The libraries require that something is passed in as command even if the remote side executes something automatically. 这些库要求将某些内容作为命令传递,即使远程端自动执行某些操作。

See also documentation for the single host SSHClient of the same project. 另请参见同一项目的单个主机SSHClient的文档。

Per documentation, line parsing and encoding are handled by the library which is also cross-platform. 根据文档,行解析和编码均由跨平台的库处理。

There are others like paramiko and ssh2-python that are lower level and need more code for the equivalent above - see their respective home pages for examples. 还有其他一些工具,例如paramiko和ssh2-python,它们是较低的级别,并且需要与以上等效的更多代码-示例请参见各自的主页。

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

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