自動EOFが名前付きパイプに転送されるのを防ぎ、必要に応じてEOFを送信します。

自動EOFが名前付きパイプに転送されるのを防ぎ、必要に応じてEOFを送信します。

与えられたストリーム(次の場合はstdin)からEOFを読み取ると自動的に終了するプログラムがあります。
ここで、名前付きパイプを生成し、プログラムの標準入力をここにリンクするシェルスクリプトを作成したいと思います。その後、スクリプトはパイプに書き込みます。何度もechocat(および終了時に自動的に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

答え1

他の人が指摘したように、パイプリーダーは作成者がいない場合はEOFを受け取ります。したがって、解決策は常に作成者にそれを有効にすることです。作成者は何も送信する必要はなく、開くだけです。

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

#!/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

パイプラインは、最後の作成者が消えたときにEOFを受け取ります。これを避けるには、常にライター(書き込み用にパイプを開くが実際には何も書き込まないプロセス)があることを確認してください。 EOFを送信するには、所有者を消すようにしてください。

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

答え3

プログラムは、「終了する時間です」を意味するEOFと、「書き込みは完了しましたが他の人の入力がある可能性があります」を意味するEOFを区別することはできません。

プログラムの動作を変更する能力がある場合は、無限ループ(EOFまで続く1回の繰り返し)を読み、「終了時間」を示す特定のコマンド文字列を送信できます。その文字列を送信することは、send_eofあなたの質問のコマンドの仕事です。

別のオプション:

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

または

{ echo some stuff; cat more_stuff.txt; } >P

関連情報