2017-04-08 89 views
1

我做的東西需要使用curl xxx | bash運行的東西。 我創建了一個python腳本與sys.stdin.readline()來測試像這樣:由乳寧python腳本「|慶典」與sys.stdin.readline()

[python3] test.py 


import sys 
def read_input(): 
    input = sys.stdin.readline().rstrip() 
    print(input) 
read_input() 

它直接運行由python3 test.py

test 
test 

但是,如果使用echo 'python3 test.py' | bash,它不會停下來讓我輸入的東西。

任何提示?

回答

2

當通過管道與|,要重定向從所述第一命令的輸出到第二輸入。這意味着第二個命令的標準輸入沒有連接到終端,因此無法讀取鍵盤輸入。因此,表格curl xxx | bash僅適用於非交互式腳本。這不是Python特有的。

,你可以在工作原則解決此通過下另一個號碼保存輸入描述符,但它確實變得相當複雜:

$ (echo 'exec <&3 3<&- ; echo script starts ; read hello ; echo you entered $hello ; exit' | bash) 3<&0 
script starts 
something 
you entered something 

在這裏,我用()創建一個子shell,在標準輸入上的文件複製描述符使用3<&0 3,而在管道中產生兩個腳本將重命名背面與exec <&3 3<&-exit小號stdin中,以防止從恢復的標準輸入被讀取進一步的命令。這有副作用,如描述符3打開echo命令。

由於主要的原因首先使用curl address | bash是保留命令簡單,這是不是你追求的。此外,如果在下載過程中出現任何問題,管道將阻止您進行處理;你的腳本可能會被中斷。傳統的下載然後運行是不是差很多:

curl -O http://somewhere/somefile.py && python somefile.py 

相比之下,這樣可以節省somefile.py到你的文件系統。這有缺點,就像需要一個可寫的文件系統並替換那個特定的文件名一樣。從正面看,如果有什麼錯了,它停在那裏,不運行腳本損壞,由於&&

最後一個可能性,如果你在命令行中下載適合的劇本可能是把它放在那裏,而不是在管:

python -c "$(curl $url)" 

這對進行中斷的下載相同的弱點,另外的地方在命令行通常爲公共信息的腳本內容(考慮ps ax輸出)。但如果你只是用curl來下載腳本,那麼關於如何獲得它的信息也是可以的。由於這不會重定向標準輸入,它可能是您的直接問題的答案。

一般情況下,我建議運行任何腳本直接關閉互聯網,而無需驗證,因爲這curl something | bash命令行一樣。它太容易受到劫持,因爲任何步驟都沒有涉及驗證。最好使用一個檢查簽名的軟件包庫,比如apt。

另一種在Linux上訪問終端的方法是通過設備/dev/tty。該方法用於例如when ssh asks for a password。也可以重新打開stdout或stderr以進行輸入,如(exec < /dev/null ; read foo <&2 ; echo $foo)