考虑下面的脚本
#!/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 没有读者,那么 echo 是否不应该等待?当我在终端中执行此操作时,它会按预期挂起
❯ 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
来减慢生产者的速度,您可能只会得到一个。