【发布时间】:2019-04-13 20:27:30
【问题描述】:
我正在编写一个脚本来设置机器环境。我有能力在机器上放置一个启动脚本,所以我尝试在我的“工作站”机器上使用 unix 中的命名管道mkfifo,当这些新机器上线时,它将监听来自这些新机器的写入。
问题是,我无法控制这些机器何时上线。总共有 20 多台机器同时启动,我试图模拟命名管道在有机会读取之前被多次写入的效果,并产生了惊人的结果....
我写了两个小测试脚本:
mkfifogen.sh
#!/bin/bash
mkfifo h
testing=""
sleep 10
for((i=0;i<5;i++));do
echo $I
while read line;do
testing+="$line"
done < h
done
echo "$testing"
rm -f h
和
mkfifowrite.sh
#!/bin/bash
for((i=0;i<5;i++));do
echo "this is a test $i" > h
done
当我运行 mkfifogen.sh 后跟 mkfifowrite.sh 时,输出如下
0
1
2
然后mkfifowrite.sh脚本退出,mkfifogen.sh脚本挂起
然后我必须再运行 mkfifowrite.sh 脚本 3 次,每次都会导致 mkfifogen.sh 脚本上的输出再增加一次。最后一次运行会导致 testing 的值输出 4 次,所以我的 mkfifowrite.sh 脚本运行 4 次和 mkfifogen.sh 脚本运行一次后的输出如下所示:
0
1
2
3
4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
在运行 mkfifogen.sh 和 mkfifowrite.sh 后,我期望看到的是:
0
1
2
3
4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
我在网上看了很多,对此有一些神秘的答案,但我似乎无法从中理解。我觉得这个链接可能是我的答案,但我不确定https://unix.stackexchange.com/questions/68146/what-are-guarantees-for-concurrent-writes-into-a-named-pipe
TL;DR:
如何确保对命名管道的所有写入(无论它们执行的速度如何)都由读取独立处理?
【问题讨论】:
-
投反对票,你有理由吗?如果是这样,请评论我如何改进我的问题...
-
这有点棘手。首先,您是有意在每次迭代时打开和关闭
mkfifowrite.sh中的管道,还是希望mkfifowrite.sh的单次运行对应mkfifogen.sh中for循环的单次迭代?其次,根据我使用的bash的版本,以及我是在macOS 还是Linux 下运行它,我得到了不同的结果。您使用的是哪个版本的bash? -
是的,for 循环的每次迭代都会模拟对管道的不同写入,就像一台机器上线并中继其状态一样。我在 RHEL 上运行它。 @chepner
-
基本上,我想了解在读取尝试读取第一个之前,当写入在管道上堆积时会发生什么。
-
请注意,您不是在测试并发写入;你有一个读者和一个作家,而那个作家只是在进行一系列顺序写入。如果您尝试在 parallel 中多次运行
mkfifowrite.sh,就会出现真正的问题。
标签: linux bash unix pipe named-pipes