Proc

寫入程序的標準輸入

  • April 10, 2022

據我了解,如果我輸入以下內容……

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 ncsocat將 python 程序綁定到簡單的套接字來執行此操作。或者編寫一個簡單的 python 應用程序,綁定到埠並偵聽要在套接字上解釋的命令。

套接字可以是本地的,並且不會暴露給任何 Web 界面。


問題是,如果你python從命令行開始,它通常會附加到你的 shell,它連接到終端,實際上我們可以看到

$ ls -al /proc/PID/fd
lrwxrwxrwx 1 USER GROUP 0 Aug 1 00:00 0 -> /dev/pty1

因此,當您寫入stdinpython 時,您實際上是在寫入pty偽終端,它是一個核心設備,而不是一個簡單的文件。它使用ioctlnot readand write,因此您將在螢幕上看到輸出,但不會將其發送到生成的程序 ( python)

複製您正在嘗試的內容的一種方法是使用fifoor named 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 的答案

引用自:https://unix.stackexchange.com/questions/385771