为什么等待'不等待分离的工作

时间:2014-05-15 21:10:31

标签: linux bash sorting

我跟着这个blog entry通过拆分大文件,排序和合并来并行排序。 步骤是:

  1. split -l5000000 data.tsv '_tmp'
  2. ls -1 _tmp* | while read FILE; do sort $FILE -o $FILE & done
  3. sort -m _tmp* -o data.tsv.sorted
  4. 在步骤2和3之间,必须等到排序步骤完成。 我假设没有任何参数的wait是正确的,因为根据man页面,如果wait被调用而没有参数all currently active child processes are waited for

    但是,当我在shell中尝试此操作时(即执行步骤1和2,然后执行wait),wait会立即返回,但top显示sort流程仍在运行。

    最终我想用它来提高脚本的速度,所以它不是我可以在shell上手动完成的一次性事情。

    我知道自{8}版以来sort有一个--parallel选项,但是在我运行它的群集上,安装了旧版本,我也很好奇如何解决这个问题。< / p>

2 个答案:

答案 0 :(得分:3)

这是一个简单的测试用例,可以解决您的问题:

true | { sleep 10 & }
wait
echo "This echos immediately"

问题是管道创建了一个子shell,而forked进程是该子shell的一部分。解决方案是在子shell中等待而不是主要的父shell:

true | { sleep 10 & wait } 
echo "This waits"

转换回您的代码,这意味着:

ls -1 _tmp* | { while read FILE; do sort $FILE -o $FILE & done; wait; }

答案 1 :(得分:1)

来自the bash man page

  

管道中的每个命令都作为一个单独的进程执行(即在子shell中)。

因此,当您管道到while时,会创建一个子shell。步骤2中的其他所有内容都在此子shell中执行(即,所有后台进程)。然后脚本退出while循环,离开子shell,wait在父shell中执行,没有什么可以等待的。您可以使用process substitution

来避免使用管道
while read FILE; do 
    sort $FILE -o $FILE & 
done < <(ls -1 _tmp*)