寫入程序的標準輸入
據我了解,如果我輸入以下內容……
python -i
… python-interpreter 現在將從 stdin 讀取,行為(顯然)像這樣:
>>> print "Hello" Hello
如果我這樣做,我希望它會做同樣的事情:
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
但這是輸出(作為一個實際的空行):
>>> print "Hello" <empyline>
這在我看來,它只是把它
print "Hello"\n
寫到stdout
,但沒有解釋它。為什麼這不起作用,我該怎麼做才能使它起作用?
以這種方式向 shell/解釋器發送輸入非常容易出現問題,並且很難以任何可靠的方式工作。
正確的方法是使用套接字,這就是發明它們的原因,您可以在命令行中使用
ncat
nc
或socat
將 python 程序綁定到簡單的套接字來執行此操作。或者編寫一個簡單的 python 應用程序,綁定到埠並偵聽要在套接字上解釋的命令。套接字可以是本地的,並且不會暴露給任何 Web 界面。
問題是,如果你
python
從命令行開始,它通常會附加到你的 shell,它連接到終端,實際上我們可以看到$ ls -al /proc/PID/fd lrwxrwxrwx 1 USER GROUP 0 Aug 1 00:00 0 -> /dev/pty1
因此,當您寫入
stdin
python 時,您實際上是在寫入pty
偽終端,它是一個核心設備,而不是一個簡單的文件。它使用ioctl
notread
andwrite
,因此您將在螢幕上看到輸出,但不會將其發送到生成的程序 (python
)複製您正在嘗試的內容的一種方法是使用
fifo
ornamed pipe
。# make pipe $ mkfifo python_i.pipe # start python interactive with pipe input # Will print to pty output unless redirected $ python -i < python_i.pipe & # keep pipe open $ sleep infinity > python_i.pipe & # interact with the interpreter $ echo "print \"hello\"" >> python_i.pipe
您也可以
screen
僅用於輸入# start screen $ screen -dmS python python # send command to input $ screen -S python -X 'print \"hello\"' # view output $ screen -S python -x
訪問不會訪問程序PID的文件描述符 0 ,它訪問PID在文件描述符 0 上打開的文件。這是一個微妙的區別,但它很重要。文件描述符是程序與文件的連接。無論文件是如何打開的,寫入文件描述符都會寫入文件。
/proc/*PID*/fd/0
如果是正常文件,寫入它會修改文件。數據不一定是程序接下來要讀取的數據:它取決於附加到程序用來讀取文件的文件描述符的位置。當一個程序打開時,它會得到與另一個程序相同的文件,但文件位置是獨立的。
/proc/*PID*/fd/0``/proc/*PID*/fd/0
如果是一個管道,那麼寫入它會將數據附加到管道的緩衝區中。在這種情況下,從管道讀取的程序將讀取數據。
/proc/*PID*/fd/0
如果是一個終端,那麼寫入它會在終端上輸出數據。終端文件是雙向的:寫入它會輸出數據,即終端顯示文本;從終端讀取輸入數據,即終端傳輸使用者輸入。
/proc/*PID*/fd/0
Python 既可以讀取也可以寫入終端。當您執行時
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
,您正在寫入print "Hello"
終端。終端print "Hello"
按指示顯示。python 程序沒有看到任何東西,它仍在等待輸入。如果您想向 Python 程序提供輸入,則必須讓終端來執行此操作。有關執行此操作的方法,請參見crasic 的答案。