如何在循环中运行固定数量的进程?

时间:2015-09-08 17:40:48

标签: bash parallel-processing wait

我有一个这样的脚本:

#!/bin/bash
for i=1 to 200000
do
create input file
run ./java
done

我需要同时运行一个(8或16)个进程(java)并且我不知道如何操作。我知道wait可能会有所帮助,但它应该一直运行8个进程,而不是等到前8个进程完成另一个8进程。

3 个答案:

答案 0 :(得分:4)

bash 4.3为wait命令-n添加了一个有用的新标记,导致wait阻止,直到任何单个后台作业,而不仅仅是给定子集(或所有)的成员,以完成。

#!/bin/bash
cores=8  # or 16, or whatever
for ((i=1; i <= 200000; i++))
do
    # create input file and run java in the background.
    ./java &

    # Check how many background jobs there are, and if it
    # is equal to the number of cores, wait for anyone to
    # finish before continuing.
    background=( $(jobs -p) )
    if (( ${#background[@]} == cores )); then
        wait -n
    fi
done

存在一个小的竞争条件:如果您处于最大负载但是之后完成作业,则运行jobs -p,您仍将阻止直到另一个工作 完成。你无能为力,但在实践中不应该有太多麻烦。

bash 4.3之前,您需要定期轮询后台作业集,以查看池何时降至阈值以下。

while :; do
    background=( $(jobs -p))
    if (( ${#background[@]} < cores )); then
        break
    fi
    sleep 1
done

答案 1 :(得分:2)

像这样使用GNU Parallel,简化为20个作业而不是200,000个,第一个作业是echo而不是&#34;创建文件&#34; 和第二个作业工作是sleep而不是&#34; java&#34;

seq 1 20 | parallel -j 8 -k 'echo {}; sleep 2'

-j 8说明一次要运行多少个工作。 -k表示保持输出顺序。

这是一个输出的小动画,所以你可以看到时间/顺序:

enter image description here

答案 2 :(得分:1)

使用非古老版本的GNU实用程序或在* BSD / OSX上,使用xargs-P选项并行运行进程。

#!/bin/bash
seq 200000 | xargs -P 8 -n 1 mytask

其中mytask is an auxiliary script, with the sequence number (the input line) available as the argument $ 1`:

#!/bin/bash
echo "Task number $1"
create input file
run ./java

如果需要,您可以将所有内容放在一个脚本中:

#!/bin/bash
seq 200000 | xargs -P 8 -n 1 sh -c '
  echo "Task number $1"
  create input file
  run ./java
' mytask

如果您的系统没有seq,则可以使用bash代码段

for ((i=1; i<=200000; i++)); do echo "$i"; done

或其他shell工具,例如

awk '{for (i=1; i<=200000; i++) print i}' </dev/null

</dev/zero tr '\0' '\n' | head -n 200000 | nl