2016-03-07 117 views
1

我想通過其標準輸入/輸出(遠程)非交互殼運行多個命令和讀取的輸出進行通信。問題是,如果我在shell stdin中填充多個命令,我無法檢測到各個命令的輸出之間的界限。運行在非交互式shell會話多個命令和解析輸出

在Python般的僞代碼:

sh = Popen(['ssh', '[email protected]', '/bin/bash'], stdin=PIPE, stdout=PIPE) 
sh.stdin.write('ls /\n') 
sh.stdin.write('ls /usr\n') 
sh.stdin.close() 
out = sh.stdout.read() 

但顯然out包含串聯這兩個命令的輸出,我也沒有可靠地分裂他們的方式。

到目前爲止,我的最好的辦法是在輸出之間插入\0字節:

sh.stdin.write('ls /; echo -ne "\0"\n') 
sh.stdin.write('ls /usr; echo -ne "\0"\n') 

然後我可以在零個字符分割out

  • 我不想每運行命令單獨SSH會話,因爲握手是太重量級:

    不爲我工作的其他方法。

  • 我寧願不給力,在創建殼ControlMaster選擇尊重最終用戶的ssh_config中。
  • 我寧願沒有必要要求用戶安裝特定的服務器程序。

是否有更好的方式在一個會話中運行幾個命令並獲取單獨的輸出?是否有一種廣泛部署的shell具有某種二進制輸出模式?

PS。有一個重複的問題,但它沒有一個滿意的答案: Run multiple commands in a single ssh session using popen and save the output in separate files

+1

如果你可以運行像Python在遠程系統上的腳本,你總是可以通過命令,並在鹹菜或JSON的輸出編碼。儘管你可以保證輸出不會包含空字符,但你的方法對我來說似乎還可以。它與多部分MIME編碼類似,除了使用通常包含長隨機字符的邊界字符串以最小化衝突的可能性。 –

+1

你可以改變你的過程到一個循環?對於每個命令,編寫命令,刷新緩衝區,然後讀取結果? –

+1

先生美洲駝,沒有辦法檢測到發出的命令已經完成運行(而不是僅僅產生下一塊輸出)。 –

回答

1

對於SSH我用paramiko及其invoke_shell方法來創建一個程序,管理shell實例。

以下不是一個完整的答案,它仍然是哈克,但我覺得這是朝着正確方向邁出的一步。

我需要在Windows中具有相同的讀/寫shell實例功能,但沒有運氣,所以我將您的方法略微擴展了一點(謝謝你的想法)。

我通過在每個命令之間放置條件退出來驗證每個命令是否基於其退出代碼成功執行,然後使用所述條件檢查(已知字符串)的文本作爲分隔符來定義每個命令的響應。

粗例如:

from subprocess import Popen, PIPE 

sh = Popen('cmd', stdin=PIPE, stdout=PIPE) 
sh.stdin.write(b'F:\r\n') 
sh.stdin.write(b"if not %errorlevel% == 0 exit\r\n") 
sh.stdin.write(b'cd F:\\NewFolder\r\n') 
sh.stdin.write(b"if not %errorlevel% == 0 exit\r\n") 
sh.stdin.write('...some useful command with the current directory confirmed as set to F:\NewFolder...') 
sh.stdin.close() 
out = sh.stdout.read() 
sh.stdout.close() 
# Split 'out' by each line that ends with 'if not %errorlevel% == 0 exit' and do what you require with the responses