GNU并行忽略管道命令

时间:2016-08-09 20:19:06

标签: bash parallel-processing gnu gnu-parallel

我最终尝试将并行用作简单的作业队列管理器,即here。想法似乎是将命令放在一个文件中,让尾部读取文件(使用-f选项以便它继续查找新行),然后将tail的输出管道并行。所以我试试

true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo {} ::: a b c >> jobqueue

但没有任何反应。好的......测试一下,我就试试

cat jobqueue | parallel

给出了

{} ::: a b c

同时

parallel echo {} ::: a b c

正确输出

a
b
c

那么为什么并行在从文件中提取时会忽略parallel-ish语法,但是当它直接给出命令时运行正常?

FWIW这是版本20160722,由于我没有机器上的root访问权限,我必须从源代码构建并安装到我的主目录。

3 个答案:

答案 0 :(得分:1)

  

那么为什么并行在从文件中提取时会忽略parallel-ish语法,但在直接给出命令时运行正常?

因为这是指定要做的事情。您将其表征为“语法”的内容在手册中定义为各种命令行参数及其部分。这些似乎主要针对在parallel命令行上给出并行化命令的情况,并且程序输入包含要操作的数据。这是xargs计划的运作模式,这是parallel的灵感之一。

事实是,你制造的东西比他们需要的更复杂。当您在其命令行上未指定命令的情况下运行parallel时,通过其输入提供命令的命令不需要 那种parallel的输入行操作操作它本身提供,并且它们通常不能以任何其他方式接受参数而不是在它们自己的命令行上。当您在该模式下运行parallel时,您只需输入您希望它运行的确切命令:

true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo a b c >> jobqueue

true > jobqueue; tail -n+0 -f jobqueue | parallel
echo echo a >> jobqueue
echo echo b >> jobqueue
echo echo c >> jobqueue

,取决于你究竟在追求什么。

至于使用tail -fparallel提供输入时似乎没有发生任何事情,我倾向于认为parallel正在等待更多输入。它的第一次读取没有返回足够的数据来触发它发送任何作业,但标准输入仍然是开放的,所以它有理由认为会有更多的输入(这确实是合适的)。如果你继续为它提供作业,那么它很快就会得到足够的输入来开始运行它们。当您准备关闭队列时,您必须kill tail命令,以便parallel知道它已到达其输入的末尾。

答案 1 :(得分:1)

来自man parallel

  

使用GNU并行作为队列系统/批处理管理器时存在一个小问题:您必须先提交JobSlot数量的作业才能启动,之后您可以一次提交一个,如果有空,则立即开始工作插槽可用。正在运行或已完成作业的输出将被保留,并且仅在JobSlots启动了更多作业时打印(除非您使用--ungroup或-u,在这种情况下,作业的输出会立即打印)。例如。如果您有10个作业点,那么第一个已完成作业的输出将仅在作业11开始时打印,而第二个已完成作业的输出仅在作业12开始时打印。

答案 2 :(得分:0)

我已经设法将一个解决方案(足够)在我的情况下拼凑起来,这是@John Bollinger的回答。

关键是我想在{em}和两个命令中输入parallel,这些参数会在某个范围内。例如,运行command1 x x范围超过1..100。现在parallel有一个有效的内置语法,即

parallel command1 ::: {1..100}

如果这就是我想做的事情,那就没关系了。但我也有command2command3等等,每个人都参与了各种参数,我想将所有这些参数都提供给parallel来管理。我希望能够在我开始运行parallel之后添加更多命令。

使用tail连续读取某些文件jobqueue,因为我在问题中提出的作为作业队列。要让tailparallel退出某些特殊字符串endoffile,我会使用

tail -f jobqueue | while read LINE
do
    echo $LINE
    [[ $LINE == *endoffile* ]] && pkill -P $$ tail
done | parallel -u -E endoffile

然后命令可以输入jobqueue,但:::语法不再有效。如果我们以传统的方式做事,事情就会奏效:

for i in {1..100}
do
    echo command1 $i >> jobqueue
done

然后最终可以使用echo endoffile >> jobqueue终止事件。