我有一个脚本一次运行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
答案 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个作业:
GNU Parallel会在完成后生成一个新进程 - 保持CPU处于活动状态,从而节省时间:
<强>安装强>
出于安全原因,您应该使用软件包管理器安装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