即使有些完成,也要经常填充四个并行进程的插槽

时间:2018-05-04 09:21:24

标签: linux bash shell unix process

我有一个脚本一次运行4个进程的批处理,我不关心每个proc的返回代码。我不想同时运行4个以上的过程。以下方法的问题是它一次最多不填充4个过程。例如,如果proc2和proc3提前完成,我希望proc 5和6启动,而不是仅在1-4完成后启动。我怎样才能在bash中实现这个目标?

run_func_1 &
run_func_2 &
run_func_3 &
run_func_4 &
wait
run_func_5 &
run_func_6 &
run_func_7 &
run_func_8 &
wait

2 个答案:

答案 0 :(得分:1)

我尝试使用工作池和作业队列进行自定义实现。 新员工将在完成前一个工作后立即从队列中获取工作。

您可以根据需要调整此脚本,但我希望您能看到我的意图。

这是脚本:

#!/bin/bash

f1() { echo Started f1; sleep 10; echo Finished f1; }
f2() { echo Started f2; sleep 8; echo Finished f2; }
f3() { echo Started f3; sleep 12; echo Finished f3; }
f4() { echo Started f4; sleep 14; echo Finished f4; }
f5() { echo Started f5; sleep 7; echo Finished f5; }

declare -r MAX_WORKERS=2
declare -a worker_pids
declare -a jobs=('f1' 'f2' 'f3' 'f4' 'f5')

available_worker_index() {
    # If number of workers is less than MAX_WORKERS
    # We still have workers that are idle
    declare worker_count="${#worker_pids[@]}"
    if [[ $worker_count -lt $MAX_WORKERS ]]; then
        echo "$worker_count"
        return 0
    fi

    # If we reached this code it means
    # All workers are already created and executing a job
    # We should check which of them finished and return it's index as available
    declare -i index=0
    for pid in "${worker_pids[@]}"; do
        is_running=$(ps -p "$pid" > /dev/null; echo "$?")
        if [[ $is_running != 0 ]]; then
            echo "$index"
            return 0
        fi
        index+=1
    done

    echo "None"
}

for job in "${jobs[@]}"; do
    declare worker_index
    worker_index=$(available_worker_index)
    while [[ $worker_index == "None" ]]; do
        # Wait for available worker
        sleep 3
        worker_index=$(available_worker_index)
    done

    # Run the job in background
    "$job" &

    # Save it's pid for later
    pid="$!"
    worker_pids["$worker_index"]="$pid"
done

# Wait all workers to finish
wait

只需更改MAX_WORKERS变量即可轻松更改工作人员池的大小。

答案 1 :(得分:0)

使用GNU Parallel,它很简单:

parallel -j4 ::: run_func_{1..8}

请记住export -f这些功能。

如果未安装GNU Parallel,请使用

parallel --embed > new_script

生成嵌入GNU Parallel的shell脚本。然后,您可以简单地更改new_script的结尾。

默认情况下,它将为每个cpu-core运行一个作业。这可以使用--jobs进行调整。

GNU Parallel是一个通用的并行程序,可以很容易地在同一台机器上或在你有ssh访问权限的多台机器上并行运行作业。

如果要在4个CPU上运行32个不同的作业,并行化的直接方法是在每个CPU上运行8个作业:

Simple scheduling

GNU Parallel会在完成后生成一个新进程 - 保持CPU处于活动状态,从而节省时间:

GNU Parallel scheduling

<强>安装

出于安全原因,您应该使用软件包管理器安装GNU Parallel,但如果没有为您的发行版打包GNU Parallel,则可以进行个人安装,这不需要root访问权限。这可以在10秒内完成:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

有关其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解详情

查看更多示例:http://www.gnu.org/software/parallel/man.html

观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

完成教程:http://www.gnu.org/software/parallel/parallel_tutorial.html

注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel