使用Paramiko的标准输出作为标准输入与子流程
问题描述:
如何在Python中的远程服务器上执行命令并将标准输出传递给本地命令?要做到ssh host 'echo test' | cat
在Python,我已经试过使用Paramiko的标准输出作为标准输入与子流程
import paramiko
import subprocess
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('host', username='user')
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('echo test')
proc = subprocess.Popen(['cat'], stdin=ssh_stdout)
outs, errs = proc.communicate()
print(outs)
,但我得到的异常'ChannelFile' object has no attribute 'fileno'
。看来Paramiko的ssh_stdout
不能作为stdin与subprocess.Popen一起使用。
答
是的,subprocess
无法重定向“假”文件上的输出。它需要fileno
这是只与“真实”的文件定义(io.BytesIO()
也没有)。
我会做手工,如下面的代码演示:
proc = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
proc.stdin.write(ssh_stdout.read())
proc.stdin.close()
所以你告诉Popen
输入是一个管,然后在管道写ssh的输出数据(并关闭它所以cat
知道什么时候必须结束)
答
根据该文档,在ChannelFile
对象并不直接包装一个实际文件描述符(因为解密和多路分解等内SSH发生)的和,所以它不能直接被用作a文件描述符为Popen
。
喜欢的东西
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('echo test')
proc = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
while proc.poll() is not None: # (fixed)
buf = ssh_stdout.read(4096)
if not buf:
break
proc.stdin.write(buf)
可能工作;即您手动读取SSH stdout流,一次最多可读取4096个字节,并将它们写入子流程的stdin管道。 我不确定当远程命令退出时上述代码的行为如何,所以YMMV。
'while proc.poll():'并不是真的必要的,它是_wrong_。如果成功完成,它将返回0.您必须执行'while proc.poll()不是None:'以主动等待程序退出。 –