次のスクリプトを検討してください
#!/usr/bin/bash
chan=/tmp/pipe.$$
mkfifo $chan
{
for x in a b c d e
do
echo $x > $chan
done
} &
for y in 1 2 3 4 5
do
x=$(cat $chan)
echo "var $x = $y ;"
done
rm $chan
期待どおりに動作しないようです。例えば
❯ ./testpipe.sh
var a
b
c = 1 ;
^C
fifoにリーダーがいないとエコー待機してはいけませんか?端末でこれを行うと、期待どおりに停止します。
❯ mkfifo /tmp/pipe
❯ echo 1 > /tmp/pipe
^C
スクリプトでなぜ異なる動作をしますか?
修正する
毎回開かずにfdsを使うように切り替えました。
#!/usr/bin/bash
chan=/tmp/pipe.$$
mkfifo $chan
{
exec 5>"$chan"
for x in a "ba ba ba baanannna" c d e
do
echo $x >&5
done
} &
exec 6<"$chan"
for y in 1 2 3 4 5
do
read -u 6 x
echo "var $x = $y ;"
done
rm $chan
私は問題を修正したのか、それともゲームをより珍しいものにしたのかはわかりません。
❯ ./testpipe.sh
var a = 1 ;
var ba ba ba baanannna = 2 ;
var c = 3 ;
var d = 4 ;
var e = 5 ;
アップデート2
FIFOはまったく必要ありません。 procの置換だけでバックグラウンドで何かを実行し、必要に応じて読み取ることができます。生産者と消費者に省電力モードを追加する前後にテストされました。うまくいくようです。ゲームがないかもしれません。
#!/usr/bin/bash
produce()
{
for x in a "ba ba ba baanannna" "more space" d e
do
echo "$x"
done
}
exec {fd}< <(produce)
for y in 1 2 3 4 5
do
read -u $fd x
echo "var $x = $y ;"
done
答え1
Running in background shell -- running in foreground shell
echo a waits
cat opens read side
cat is maybe faulting in some pages or maybe not just picked
but for whatever reason doesn't immediately call read
echo a completes
echo b doesn't wait (read side already open) and completes
echo c ditto
cat calls read, gets a NL b NL c NL and writes them
(but the shell's $(...) that reads them drops the final NL)
echo d probably doesn't wait, but might if cat has close'd already (race condition)
成功すれば、$(cat <$chan)
すべてのaeを得ることができます。サブシェル読み込み前に cat を実行する前に読み込み側を開いて待ち時間を増やします。 OTOHプロデューサーを使用しcommand echo
たり/bin/echo
速度を遅くしたりすると、おそらく1つしか入手できません。