并行运行bash shell并等待

时间:2014-04-17 14:21:33

标签: linux bash shell parallel-processing

我在一个目录中有100个文件,并希望通过几个步骤处理每个文件,而step1非常耗时。所以伪代码就像:

for filename in ~/dir/*; do
  run_step1 filename >${filename}.out &
done

for outfile in ~/dir/*.out; do
  run_step2 outfile >${outfile}.result
done

我的问题是如何检查给定输入文件的step1是否完整。我以前在C#中使用threads.join,但不确定bash shell是否具有等价物。

4 个答案:

答案 0 :(得分:4)

看起来你想要:

for filename in ~/dir/*
do
    (
    run_step1 $filename >${filename}.out
    run_step2 ${filename}.out >${filename}.result
    ) &
done
wait

这会在单独的子shell中处理每个文件,在每个文件上运行第一步,然后执行步骤2,但并行处理多个文件。

关于您唯一需要担心的问题是确保您不要尝试并行运行太多进程。您可能需要考虑GNU parallel

你可能想写一个简单的脚本(也许是doit.sh):

run_step1 "$1" > "$1.out"
run_step2 "$1.out" > "$1.result"

然后从parallel调用该脚本,每次调用一个文件。

答案 1 :(得分:3)

试试这个:

declare -a PROCNUMS
ITERATOR=0
for filename in ~/dir/*; do
    run_step1 filename >${filename}.out &
    PROCNUMS[$ITERATOR]=$!
    let "ITERATOR=ITERATOR+1"
done

ITERATOR=0
for outfile in ~/dir/*.out; do
    wait ${PROCNUMS[$ITERATOR]}
    run_step2 outfile >${outfile}.result
    let "ITERATOR=ITERATOR+1"
done

这将使创建的进程数组按顺序等待它们,因为它们需要完成,而不是依赖于in和out文件之间存在1对1的关系而且目录不会更改它正在运行。

如果您希望假设每个文件都是独立的,那么现在也可以异步运行第二个循环。

我希望这会有所帮助,但如果您有任何疑问,请发表评论。

答案 2 :(得分:1)

The Bash builtin wait可以等待特定后台作业或所有后台作业完成。简单的方法是在两个循环之间插入wait。如果您想更具体,可以在第二个循环中直接wait PID之前保存每个后台作业的PID和run_step2

答案 3 :(得分:0)

在执行step1的循环之后,您可以编写另一个执行fg命令的循环,该命令将上一个进程移动到后台移动到前台。

您应该知道,如果某个流程已经完成,fg可能会返回错误。

在使用fg s循环后,您确定所有步骤1都已完成。