为什么我的并行命令同时打印“Starting”和“Finished”?

为什么我的并行命令同时打印“Starting”和“Finished”?
ls *.txt | parallel 'echo Starting on file {}; mkdir {.}; cd {.}; longCMD3 ../{} > /dev/null; echo Finished file {}'

这个班轮部分有效,除了 longCMD3 需要大约 3 分钟,但第一个和第二个 echo 命令几乎同时打印。我尝试放入

wait

在最后的回声之前,但这没有什么区别。

如何确保仅在 longCMD3 完成后才打印最终回显?

这是一个例子

假设我只有 4 个核心:

ls
foo1.txt foo2.txt foo3.txt foo4.txt foo5.txt foo6.txt 

我所期望的:

Starting on file foo1.txt
Starting on file foo2.txt
Starting on file foo3.txt
Starting on file foo4.txt

那么 longCMD3 至少需要 2 分钟才能完成其中一个文件

Finished file foo1.txt
Starting on file foo5.txt

但我得到的是:

Starting on file foo1.txt
Finished file foo1.txt
Starting on file foo2.txt
Finished file foo2.txt
Starting on file foo3.txt
Finished file foo3.txt
Starting on file foo4.txt
Finished file foo4.txt

这对于所有 6 个文件都是如此。每个文件的开始和完成语句都会同时打印。但每个文件之间会花费几分钟的时间。

答案1

对于每个文件,命令echo Starting on file foo.txtmkdir foocd foo和依次运行,即每个命令在前一个longCMD3 ../foo.txt > /dev/null命令echo Finished file foo.txt完成后开始。

不同文件的命令是散布的。默认情况下,parallel 命令会并行运行与核心数量一样多的作业。

但是,那输出默认情况下命令不散布。这就是为什么您看不到一堆“开始”行,然后看到相应的“完成”行。并行将每个作业的输出分组在一起。它缓冲输出直到作业完成。请参阅--group手册中该选项的说明。分组在您的情况下没有意义,因此使用--ungroup( -u) 选项将其关闭,或使用 切换到行分组--line-buffer

其他一些更正:

  • 解析 ls 不可靠。直接传递文件名parallel
  • 如果mkdir失败,则不应继续。如果任何命令失败,您应该安排作业失败。一个简单的方法是启动作业脚本set -e
parallel --line-buffer 'set -e; echo Starting on file {}; mkdir {.}; cd {.}; longCMD3 ../{} > /dev/null; echo Finished file {}' ::: *.txt

相关内容