web-dev-qa-db-ja.com

名前付きパイプから標準入力を取得する

私がやろうとしていることは、ターミナルウィンドウでpythonを実行し、それを名前付きパイプからstdinにリダイレクトすることです。次に、別のターミナルで名前付きパイプに書き込み、そのコマンドをpythonで実行します。

ターミナル1:

mkfifo p1
python < p1

ターミナル2:

echo -n "print \"Hello World\"" > p1

何が起こるか-python prints Hello Worldで終了します。私がしたいことは、次のコマンドを実行するためにpython runningを保持することです。これをシェルで行うにはどうすればよいですか?

10
Lord Loh.

必要がある

  • Stdinがターミナルではない場合でもpythonインタラクティブに実行します:python -iを使用します
  • パイプの書き込み側を開いたままにします。そうでない場合、pythonはEOFを検出して終了します。

そう:

python -i < p1

そして他の場所:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-
10

echoが書き込みを行った後、tail -fを使用してfifoを開いたままにすることができます。

tail -n1 -f p1 | python

これが機能する理由

pythonp1から読み取っています。ファイルの最後に達すると、読み取りを停止します。これは、ファイルが名前付きパイプであっても、ファイルの読み取りの通常の動作です。 tail-f(フォロー)フラグを指定すると、ファイルの終わりに達した後もファイルからの読み取りを続行します。

5
user26112

プログラム全体を一度に送信する必要があります。

Run python < p1を呼び出すと、シェルはpythonを呼び出す前に入力を待機します。つまり、pythonは実行も開始しませんまったくは、データストリーム全体がシェルによって読み取られ、全体がpython

代わりにpython -u p1を実行しても(つまり、バッファリングされずにファイルp1から読み取られます)pythonは、ファイルを実行する前にファイル全体を読み取ろうとします。

この実験を試してください。

ターミナル1:

mkfifo p1
python < p1

ターミナル2:

cat > p1
print "Hello World"
print "Hello World"

複数の行を送信できることがわかりますが、pythonは何も実行しません。次に、 ctrl+D。プログラム全体が一度に実行されます。

つまり、要約すると、pythonをパイプから読み取る必要がある場合は、プログラム全体を送信する必要があります。pythonをこの方法でインタラクティブに使用することはできません。

2
bahamat

おそらく、テールアプローチの方が優れています(柔軟性が高い)が、代替策として:

{ echo -n "print \"Hello World\""; cat; } > p1
1
Hauke Laging