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

Glu*_*ubb 3 command-line bash gnu-parallel

ls *.txt | parallel 'echo Starting on file {}; mkdir {.}; cd {.}; longCMD3 ../{} > /dev/null; echo Finished file {}'
Run Code Online (Sandbox Code Playgroud)

这个 liner 部分工作,除了 longCMD3 需要大约 3 分钟,但第一和第二个 echo 命令几乎同时打印。我试过放入

wait
Run Code Online (Sandbox Code Playgroud)

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

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

这是一个例子

假设我只有 4 个内核:

ls
foo1.txt foo2.txt foo3.txt foo4.txt foo5.txt foo6.txt 
Run Code Online (Sandbox Code Playgroud)

我的期望:

Starting on file foo1.txt
Starting on file foo2.txt
Starting on file foo3.txt
Starting on file foo4.txt
Run Code Online (Sandbox Code Playgroud)

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

Finished file foo1.txt
Starting on file foo5.txt
Run Code Online (Sandbox Code Playgroud)

但我得到的是:

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
Run Code Online (Sandbox Code Playgroud)

这对于所有 6 个文件都会继续。并且对于每个文件同时打印 Start 和 Finished 语句。但是每个文件之间会花费几分钟。

Gil*_*il' 5

对于每一个文件,命令echo Starting on file foo.txtmkdir foocd foolongCMD3 ../foo.txt > /dev/nullecho Finished file foo.txt顺序运行的,即前一后的各命令启动已完成。

不同文件的命令是穿插的。默认情况下,parallel 命令会并行运行与您拥有的内核数量一样多的作业。

然而,命令的输出默认不散布。这就是为什么你没有看到一堆“开始”行,然后是相应的“完成”行。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
Run Code Online (Sandbox Code Playgroud)