Bash中的多进程队列

时间:2016-05-19 09:22:56

标签: bash shell queue fifo

Bash中多进程队列的优秀实现是什么?

我正在考虑一个FIFO,每一行代表队列中的一个元素:

mkfifo fifo
ls > fifo

在另一个过程中:

read element < fifo

预期的结果是读者进程读取一行(即一个元素)并将其存储在变量$element中,保持队列的其余部分不变,以便其他读取器进程可以获取元素(行)好。

不幸的是,这不起作用。 read语句打开FIFO,导致编写器(ls)立即完成,关闭FIFO然后似乎导致剩余数据被丢弃,其他元素无法被另一个进程读取(在事实上,下一个read < fifo会挂起,直到另一个编写器出现并写入FIFO中。

我还考虑过触摸特殊目录中的文件(作为编写者)并移动文件(作为读者),但这似乎很乏味,显然对于数百万个队列条目是不可行的。

我能否以某种方式使FIFO变体工作?

是否有不同的实现shell队列的方法,有多个编写器和几个读取器,所有这些都在同一个队列上工作?

2 个答案:

答案 0 :(得分:1)

你只需要保持PIPE开放

$mkfifo PIPE
$cat > PIPE &

管道现在无限期打开,直到你杀了猫。

$ls > PIPE &
$read Line < PIPE
$echo $Line
 file1

您现在可以写下并阅读您的内心。

答案 1 :(得分:0)

我自己也找到了答案。我没有使用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%02d\n" "$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")。如果你想排空队列,请在循环中执行此操作。

我对投票解决方案并不是很满意,但是测试表明它可以与两位作者和两位读者一起可靠地工作(而且我不明白为什么更多的读者和作家应该提出问题)。