名前付きパイプへの自動EOFを防止し、必要なときにEOFを送信する


12

特定のストリーム(次の場合はstdin)でEOFを読み取ると自動的に終了するプログラムがあります。
次に、名前付きパイプを作成し、プログラムの標準入力をそれに接続するシェルスクリプトを作成します。その後、スクリプトは、パイプへの書き込みを数回使用echoし、cat(自動的にEOF彼らの出口を生成し、他のツールを)。私が直面している問題は、最初の処理echoが完了すると、EOFをパイプに送信してプログラムを終了させることです。このようなものを使用tail -fすると、プログラムを終了しようとするときにEOFを送信できません。私はバランスの取れた解決策を研究していますが、無駄です。
EOFを防ぐ方法とEOFを手動で送信する方法の両方をすでに見つけましたが、それらを組み合わせることができません。ヒントはありますか?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

回答:


13

他の人が示したように、パイプのリーダーは、ライターが残っていないとEOFを受け取ります。したがって、解決策は、常に1人のライターがそれを開いたままにしておくことです。そのライターは何も送信する必要はなく、開いたままにします。

シェルスクリプトを使用しているので、最も簡単な解決策は、書き込み用にパイプを開くようにシェルに指示することです。そして、終わったらそれを閉じます。

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

最後の行を省略すると、スクリプトの終了時にファイル記述子3が自動的に閉じられます(したがって、リーダーはEOFを受け取ります)。利便性は別として、スクリプトが何らかの理由で早期に終了した場合でも、これは一種の安全性を提供します。


2
これexec 3>Pはbashでハングアップする原因です、なぜですか?
Wang

@王それはすべきではない。もしそうなら、あなたはおそらく質問のPOCコードと同じことをしていないでしょう。それがブロックすると考えることができる唯一の理由は、代わりにのようなexec 2>Pことをしていて、トレースモードがオンになっている(set -x)場合で、bashはパイプに書き込みますが、リーダーがないため、待機をブロックします読むもの。
Patrick

1
@Wang @Patrick確かexec 3>Pに私のマシンでもbashでハングしています。これは、から読み取るプロセスがないためPです。したがって、解決策は、行をスワップexec 3>Pしてprogram < P &(プログラムがバックグラウンドで実行されるようにアンパサンドを追加すること)でした。
macieksk 2018年

2

最後のライターが去ると、パイプはEOFを受け取ります。これを回避するには、常にライター(書き込み用にパイプが開いているが実際には何も書き込まないプロセス)が存在するようにします。EOFを送信するには、その予備のライターを削除します。

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

0

プログラムが「終了の時間」を意味するEOFと「ライターは完了したが、他の誰かからのより多くの入力がある可能性がある」を意味するEOFを区別する方法はありません。

プログラムの動作を変更する機能がある場合は、無限ループ(EOFまで1回の反復が続く)で読み取りを行い、「終了時間」を意味する特定のコマンド文字列を送信します。その文字列を送信することsend_eofは、質問のコマンドのタスクになります。

別のオプション:

( echo some stuff; cat more_stuff.txt ) >P

または

{ echo some stuff; cat more_stuff.txt; } >P
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.