2017-06-12 147 views
1

如何在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一起使用。

回答

1

是的,subprocess無法重定向「假」文件上的輸出。它需要fileno這是隻與「真實」的文件定義(io.BytesIO()也沒有)。

我會做手工,如下面的代碼演示:

proc = subprocess.Popen(['cat'], stdin=subprocess.PIPE) 
proc.stdin.write(ssh_stdout.read()) 
proc.stdin.close() 

所以你告訴Popen輸入是一個,然後在管道寫ssh的輸出數據(並關閉它所以cat知道什麼時候必須結束)

1

根據該文檔,在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。

+1

'while proc.poll():'並不是真的必要的,它是_wrong_。如果成功完成,它將返回0.您必須執行'while proc.poll()不是None:'以主動等待程序退出。 –

相關問題