GNU Parallel 无需任何命令行选项,允许您轻松并行化最后一个参数由一行 STDIN 确定的命令:
$ seq 3 | parallel echo
2
1
3
请注意,parallel
在开始执行作业之前不会等待 STDIN 上的 EOF — 运行将立即yes | parallel echo
开始打印无限多个副本。y
但是,如果 STDIN 相对较短,则此行为似乎会发生变化:
$ { yes | ghead -n5; sleep 10; } | parallel echo
sleep 10
在这种情况下,完成之前不会返回任何输出。
这只是一个说明 - 实际上,我正在尝试从一系列不断生成的 FIFO 管道中读取数据,其中 FIFO 生成过程将不会继续,直到现有管道开始被消耗。例如,我的命令将生成一个 STDOUT 流,如下所示:
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.PFcggGR55i
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.UCpTBzI3J6
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.r2EmSLW0t9
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.5TRNeeZLmt
cat
在新终端中一次手动生成这些文件中的每一个都会导致 FIFO 生成过程成功完成。然而,跑步printfifos | parallel cat
是行不通的。相反,parallel
似乎永远阻塞等待 STDIN 上的输入 - 如果我将管道修改为printfifos | head -n4 | parallel cat
,死锁就会消失,并且前四个管道会成功打印。
此行为似乎与--jobs|-j
参数有关。虽然{ yes | ghead -n5; sleep 10; } | parallel cat
10 秒内不会产生任何输出,但添加-j1
选项会产生四行,y
然后几乎立即等待 10 秒,等待最终的y
.不幸的是,这并不能解决我的问题——我需要每一个之前要处理的参数parallel
可以通过读取 STDIN 来获取 EOF。有什么办法可以实现这一点吗?
答案1
GNU Parallel 中的一个错误是,它仅在读取每个作业槽的一个作业后才开始处理。之后它一次读取一份作业。
在旧版本中,输出也会因作业槽数量而延迟。较新的版本仅延迟单个作业的输出。
因此,如果您每秒发送一个作业,parallel -j10
它会在启动之前读取 10 个作业。在旧版本中,您必须再等待 10 秒才能看到作业 3 的输出。
解决启动时限制的方法是为每个作业槽提供一个虚拟作业以进行并行处理:
true >jobqueue; tail -n+0 -f jobqueue | parallel &
seq $(parallel --number-of-threads) | parallel -N0 echo true >> jobqueue
# now add the real jobs to jobqueue
输出要使用的解决方法--linebuffer
(但这会混合来自不同作业的整行)。