2014-10-16 72 views
5

我有一個Python腳本,我用它在多個使用Python子流程模塊的主機上並行執行命令。它包裝SSH,並且基本上使得這樣一個電話:運行Python腳本後終端搞砸(不顯示新行)

output = subprocess.Popen(["/bin/env", env, "/usr/bin/ssh", "-t", "%[email protected]%s" % (user, host), "--", command], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 

有效命令被這樣執行:

/bin/env TERM=$TERM:password /usr/bin/ssh -t "%[email protected]%s" % (user, host), "--", command 

它工作正常,但我得到一個間歇性的錯誤在我的終端得到弄糟(失去換行符)後運行腳本。命令行中的「重置」修復了它,但我不確定這是如何發生的,確切地說。我注意到有時在元組輸出中的第一項的末尾有一個「\ r \ n」,有時它不在那裏。請參閱下,特別是「權限被拒絕\ r \ n」

**** Okay output **** 
[[email protected]/home/user]# ./command.py hosts.lists "grep root /etc/shadow" 
Running command "grep root /etc/shadow" on hosts in file "hosts.test" 
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server1.example.com closed.\r\n') 
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server2.example.com closed.\r\n') 
[[email protected]/home/user]# 


**** Output causes terminal to not display newlines **** 
[[email protected]/home/user]# ./command.py hosts.list "grep root /etc/shadow" 
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server1.example.com closed.\r\n') 
('grep: /etc/shadow: Permission denied\n', 'Connection to server2.example.com closed.\r\n') 
           [[email protected]/home/user]# [[email protected]/home/user]# [[email protected]/home/user] 

第二輸出已略作修改,但顯示缺少的「\ r」,我的提示如何得到「wacked」在運行腳本之後。

我認爲這與在我的subprocess命令中使用「-t」選項有關。不知怎的,我失去了\ r。如果我刪除了「-t」選項,這個問題就會消失,但長話短說,我需要它來傳遞環境變量以供在遠程機器上使用(我瘋狂地使用TERM變量來傳遞用戶的密碼sudo的目的,因爲我不能假定AcceptEnv允許在遠程sshd服務器上傳遞任意變量;我這樣做是爲了避免在命令行上傳遞密碼,這會在遠程計算機的進程列表中顯示)。

想知道是否有人知道一種方法來解決這個問題,而不刪除「-t」選項?

更新:我的劇本里 它看起來像我的tty設置獲得運行subprocess.Popen(...)後改變通信()命令,不管我是否真正打印輸出屏幕。我覺得很奇怪。這裏有前/在我的TTY配置的差異(從的stty -a)後:

-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff 
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff 


opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 

isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt 
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt 

我不知道如何停止改變我的終端設置通信()?這是可能的,還是這是一個錯誤?

+0

* *命令實際上是否需要'-t' ssh選項? – jfs 2014-10-17 21:02:35

+0

'.communicate()'不會改變你的tty設置。嘗試一些curses Python腳本,它不會在退出時將其設置恢復爲*命令*,並查看您是否可以可靠地重現該錯誤,即使腳本接受是否在退出時恢復tty的標誌。 – jfs 2014-10-17 21:06:08

+0

例如,如果在[此腳本](http://stackoverflow.com/a/327072/4279)中傳遞了「--no-restore」標誌,那麼'finally'塊中可以不做任何事情。 – jfs 2014-10-17 21:13:34

回答

4

我在Perl腳本中遇到同樣的問題。爲了解決這個問題,我必須保存本地終端的當前設置(以便在腳本結尾處恢復它),並在執行遠程命令前預先添加「stty -raw」。

在Perl

所以:

#Save當前終端設置(您可能添加PID在文件名)

`的stty -g>〜/ TMP/.currentTtySettings`;

#Execute遠程命令前面加上 「的stty -raw」

我@出來=`的ssh -t -q [email protected]。com「stty -raw; grep root/etc/shadow」`;

#Restore終端設置

`的stty \`貓〜/ TMP/.currentTtySettings \``;

希望它能幫助你!

其他非常有用的鏈接:

ssh和TTY(-t選項)https://unix.stackexchange.com/questions/151916/why-is-this-binary-file-being-changed

- 一些Perl和SSH靈感 - 詳細解釋http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.09/lib/Net/SSH/Expect.pod

- 如何避免 「-t」 爲須藤https://unix.stackexchange.com/questions/122616/why-do-i-need-a-tty-to-run-sudo-if-i-can-sudo-without-a-password

0

我發現

stty sane 

將控制檯恢復到之前的狀態。 我真的不明白在這裏的其他答案,所以我這有助於某人。

找到了答案here