命名管道在脚本中过早关闭?
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
停止。为什么我的写入脚本停止了?这是我正在做的一个小测试,目的是尝试更好地理解管道,因为我将把所有日志发送到管道,以便我可以在将它们写入文件之前对其进行解析。
我在这里缺少什么?
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
I have two terminals open, one running write.sh
and another running read.sh
. When I start write.sh
first, it hangs (like it should). Then I go to the other terminal and start read.sh
and it prints out "blah"
a ton of times, then my write.sh
stops. Why is my write script stopping? This is a little test I'm doing to try and understand pipes a little better because I'm going to be sending all my logs to a pipe so I can parse through them before writing them to a file.
What am I missing here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要获得非阻塞管道行为,您还可以首先在
fifo
上打开读取文件描述符,然后打开写入文件描述符。另请参阅:如何在脚本中使用 exec 3>myfifo,而不让 echo foo>&3 关闭管道?
To get non-blocking piping behaviour you could also first open a read file descriptor and then a write file descriptor on
fifo
.See also: How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?
这里有一个竞争条件。无论哪个脚本首先执行其内部循环命令(分别为 cat 和 echo),都将阻塞并等待另一个脚本执行其内部循环命令。但是,一旦脚本同步,如果 cat 在 echo 执行其 write() 之前在管道上调用 close() ,则 echo 将被发送 SIGPIPE 并且您的脚本将退出。您无法写入已被读取器关闭的管道。
如果您将阅读器更改为 tail -f 而不是带有 cat 的 while 循环,则阅读器将保持活动状态,而不是永久打开和关闭 fifo,并且您不应该收到 SIGPIPE。
参考: man fifo
There is a race condition here. Whichever script executes its inner loop command first (cat and echo respectively) will block and wait for the other script to execute its inner loop command. However, once the scripts syncronize, if the cat calls close() on the pipe before the echo executes its write() , the echo will be sent a SIGPIPE and your script will exit. You cannot write to a pipe that has been closed by its reader.
If you change your reader to tail -f instead of a while loop with cat, the reader stays alive rather than opens and closes the fifo in perpetuity and you should not get a SIGPIPE.
reference: man fifo