名前付きパイプからstdinを取得する

名前付きパイプからstdinを取得する

私が望むのは、ターミナルウィンドウでPythonを実行し、名前付きパイプから標準入力をリダイレクトすることです。次に、別の端末の名前付きパイプに書き込んで、Pythonでコマンドを実行します。

ターミナル1:

mkfifo p1
python < p1

NO2。ターミナル:

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

何が起こるか - Pythonが印刷してHello World終了します。私が望むのは、Pythonを実行し続けて次のコマンドを受け入れることです。シェルでこれを行うにはどうすればよいですか?

ベストアンサー1

あなたはする必要があります

  • 標準入力が端末でない場合でも、Pythonを対話的に実行するには、次のようにします。python -i
  • パイプの書き込み端を開いたままにします。それ以外の場合、PythonはEOFを検出して終了します。

だから:

python -i < p1

そして他の場所では:

# open p1 on fd 3 of the shell process¹ for instance so stdout is
# left untouched in case you still want to write messages there.
exec 3> p1

# write something on fd 3. For instance with ksh/zsh's print
# builtin:
print -u3 '1j*1j'

# or for commands such as echo that can only print things
# on stdout (fd 1), duplicate that fd 3 to their fd 1:
echo '1j*1j' >&3 # short for 1>&3

# after echo (a builtin² in virtually all shells) returns, fd 1
# is restored to what it was before, but fd 3 remains open on
# the writing end of the pipe, so python still doesn't see EOF
# there.

echo normal message on stdout
echo 1+1 >&3 # more instructions for python
...
# and when done, close that file descriptor so python sees the EOF
# (assuming that fd 3 was the only file descriptor left open on
# the writing end of that pipe):
exec 3>&-

exec特にスクリプトでは、3を使用してfdを手動で開閉するのではなく、コマンドグループ全体をリダイレクトできます。

{
  echo ... >&3
  ...
  ...
} 3> p1

¹ fd 3は、子プロセスと(ksh93にclose-on-execフラグが設定されている場合を除く)、そのプロセスで実行される他のコマンド(存在する場合)によって継承されます。

²もちろん、これは組み込まれていないコマンドにも当てはまります。組み込みのプログラムでは、コマンドを実行するために分岐されたサブプロセスでのみリダイレクトが行われるため、シェルはfd 1を保存して復元する必要はありません。この操作を自動的に実行するksh93以外の外部コマンドの場合、実際にfd 3をオフにしてリークすることなく、最終的にバックグラウンドプロセスが生成される可能性があります(cmd >&3 3>&-)。

³この場合、ksh93はfd 3にclose-on-execフラグを設定しません。

おすすめ記事