我跟着这个blog entry通过拆分大文件,排序和合并来并行排序。 步骤是:
split -l5000000 data.tsv '_tmp'
ls -1 _tmp* | while read FILE; do sort $FILE -o $FILE & done
sort -m _tmp* -o data.tsv.sorted
在步骤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>
答案 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)
管道中的每个命令都作为一个单独的进程执行(即在子shell中)。
因此,当您管道到while
时,会创建一个子shell。步骤2中的其他所有内容都在此子shell中执行(即,所有后台进程)。然后脚本退出while循环,离开子shell,wait
在父shell中执行,没有什么可以等待的。您可以使用process substitution:
while read FILE; do
sort $FILE -o $FILE &
done < <(ls -1 _tmp*)