LS:
prwx------ 1 root root 0 fifo
write.sh:
#! /bin/bash
while true;
do
echo "blah" > fifo
done
read.sh:
#! /bin/bash
while true;
do
cat fifo
done
我打开了两个终端,一个正在运行write.sh
,另一个正在运行read.sh
。当我首先启动write.sh
时,它会挂起(就像它应该的那样)。然后我转到另一个终端并开始read.sh
,它打印出"blah"
很多次,然后write.sh
停止。为什么我的写脚本会停止?这是一个小小的测试,我正在尝试更好地理解管道,因为我将把所有日志发送到管道,所以我可以在将它们写入文件之前解析它们。
我在这里缺少什么?
答案 0 :(得分:5)
这里有竞争条件。无论哪个脚本首先执行其内部循环命令(分别为cat和echo)将阻塞并等待另一个脚本执行其内部循环命令。但是,一旦脚本同步,如果cat在echo执行其write()之前调用管道上的close(),则回送将发送一个SIGPIPE,您的脚本将退出。您无法写入已被其阅读器关闭的管道。
如果你将你的阅读器更改为tail -f而不是带有cat的while循环,那么阅读器会保持活着而不是打开并永久关闭fifo并且你不应该得到一个SIGPIPE。
参考:man fifo
答案 1 :(得分:5)
要获得非阻塞管道行为,您还可以先在fifo
上打开读取文件描述符,然后打开写入文件描述符。
# cf. https://stackoverflow.com/questions/2776994/tee-a-pipe-asynchronously
(
rm -f fifo
mkfifo fifo
exec 3<fifo # open fifo for reading
trap "exit" 1 2 3 15
exec cat fifo | nl
) &
bpid=$!
(
exec 3>fifo # open fifo for writing
trap "exit" 1 2 3 15
while true;
do
echo "blah" > fifo
done
)
#kill -TERM $bpid
另请参阅:How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?