Bash中多进程队列的良好实现是什么?
我正在考虑一个FIFO,每一行代表队列中的一个元素:
mkfifo fifo
ls > fifo
在另一个过程中:
read element < fifo
预期的结果是,读取器进程读取一行(即一个元素)并将其存储在变量$element
中,使队列的其余部分保持不变,以便其他读取器进程也可以获得元素(行)。
不幸的是,这不起作用。read
语句打开FIFO,导致写入程序(ls
)立即完成,然后关闭FIFO似乎会导致剩余数据被丢弃,其他元素无法由另一个进程读取(事实上,下一个read < fifo
挂起,直到另一个写入程序出现并写入FIFO)。
我还考虑过触摸特殊目录中的文件(作为编写器),并将文件移走(作为读取器),但这似乎很乏味,对于数百万队列条目来说显然是不可行的。
我能让FIFO变体以某种方式工作吗?
有没有不同的方法来实现shell队列,让几个编写器和几个读取器都在同一个队列上工作?
我自己可能已经找到了答案。我使用的不是FIFO,而是一个最小化的TCP服务器,它接受来自一个端口的输入,并逐行将输出写入另一个端口。
为了设置TCP服务器,我使用以下脚本:
nc -k -l 4444 | while read a
do echo "$a" | nc -l 4445
done
(当然,附加&
可以在后台运行。)
然后作者可以这样做:
for ((i=0; i<10000; i++))
do
printf "x%02dn" "$i"
done >/dev/tcp/127.0.0.1/4444
读者可以这样做:
while ! { read a < /dev/tcp/localhost/4445; } 2>/dev/null
do
sleep 2 # we poll; if there is nothing, we sleep between polls
done
echo "$a"
此脚本获取一个元素(行)并对其进行处理(echo "$a"
)。如果您想排出队列,请循环执行此操作。
我对民意调查解决方案不太满意,但测试表明,它在两个作者和两个读者的情况下可靠地工作(我不明白为什么更多的读者和作者会带来问题)。
您只需要保持PIPE打开
$mkfifo PIPE
$cat > PIPE &
管道现在无限期地打开,直到你杀死猫。
$ls > PIPE &
$read Line < PIPE
$echo $Line
file1
你现在可以随心所欲地写作和阅读了。