いくつかのデータをパイプに出力し、他のプロセスに1行ずつデータを処理させます。おもちゃの例を次に示します。
mkfifo pipe
cat pipe&
cat >pipe
これで、好きなものを入力でき、Enterを押すとすぐに同じ行が表示されます。ただし、2番目のパイプをecho
で置き換える場合:
mkfifo pipe
cat pipe&
echo "some data" >pipe
パイプはecho
およびcat pipe&
が終了した後に閉じられるため、パイプを介してこれ以上データを渡すことはできません。パイプとデータを受信するプロセスを閉じないようにする方法はありますか?それにより、bashスクリプトからパイプを介して多くのデータ行を渡し、それらが到着したときに処理することができますか?
FIFO=が読み取り用に開かれている場合、呼び出しプロセスをブロックします(通常)。プロセスがFIFO書き込み用に開かれている場合、リーダーはブロック解除されます。ライターがFIFOを閉じると、読み込みプロセスはEOF(読み込む0バイト)を取得し、FIFOしたがって、ループを使用する必要があります。
mkfifo pipe
(while cat pipe; do : Nothing; done &)
echo "some data" > pipe
echo "more data" > pipe
別の方法は、FIFO open。
mkfifo pipe
sleep 10000 > pipe &
cat pipe &
echo "some data" > pipe
echo "more data" > pipe
Fifoに出力するすべてのステートメントを同じサブシェルに配置します。
# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Write to pipe.
(
echo one
echo two
) >pipe
さらに複雑な場合は、書き込み用のパイプを開くことができます。
# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Open pipe for writing.
exec 3>pipe
echo one >&3
echo two >&3
# Close pipe.
exec 3>&-
これは、パイプの読み取り側を読み取り/書き込みモードで開くことで非常に簡単に解決できます。リーダーはEOFを取得するのは、最後のライターが閉じたときだけです。読み取り/書き込みで開くと、常に少なくとも1人のライターが存在することが保証されます。
2番目の例を次のように変更します。
mkfifo pipe
cat <>pipe &
echo "some data" >pipe
正直なところ、これを機能させるための最良の方法は、基本的に2つのソケットを接続するsocat
を使用することでした。
mkfifo foo
socat $PWD/foo /dev/tty
新しい用語では、次のことができます。
echo "I am in your term!" > foo
# also (surprisingly) this works
clear > foo
欠点はsocatが必要なことです。これは誰もが手に入れる基本的なユーティリティではありません。プラス面は、機能しないものが見つからないことです...色を印刷したり、tee
をfifoに出力したり、画面をクリアしたりできます。ターミナル。
パイプのクローズをサポートするために、ジョナサンレフラーの回答から2番目のバージョンを強化しました。
dir=`mktemp -d /tmp/temp.XXX`
keep_pipe_open=$dir/keep_pipe_open
pipe=$dir/pipe
mkfifo $pipe
touch $keep_pipe_open
# Read from pipe:
cat < $pipe &
# Keep the pipe open:
while [ -f $keep_pipe_open ]; do sleep 1; done > $pipe &
# Write to pipe:
for i in {1..10}; do
echo $i > $pipe
done
# close the pipe:
rm $keep_pipe_open
wait
rm -rf $dir
ここでの他のソリューションの代替として、コマンドへの入力としてループでcat
を呼び出すことができます。
mkfifo pipe
(while true ; do cat pipe ; done) | bash
これで、コマンドを1つずつフィードでき、閉じません。
echo "'echo hi'" > pipe
echo "'echo bye'" > pipe
もちろん、必要なときにプロセスを強制終了する必要があります。これは、プロセスを作成するときに非終了動作を指定できるため、最も便利なソリューションだと思います。