我想要达到的目标是:
#!/bin/sh
concurrency_limit 3
#takes 5 min
(/usr/bin/my-process-1 --args1 && /usr/bin/my-process-2 --args1) &
#takes 10 min
(/usr/bin/my-process-1 --args2 && /usr/bin/my-process-2 --args2) &
#takes 15 min
(/usr/bin/my-process-1 --args3 && /usr/bin/my-process-2 --args3) &
#takes 5 min
(/usr/bin/my-process-1 --args4 && /usr/bin/my-process-2 --args4) &
#takes 10 min
(/usr/bin/my-process-1 --args5 && /usr/bin/my-process-2 --args5) &
#takes 20 min
(/usr/bin/my-process-1 --args6 && /usr/bin/my-process-2 --args6) &
wait max_limit 1200
echo all processes complete
总体预期最长执行时间为20分钟( - + 1分钟),假设我有3个cpu核心可用,并且我不希望同时运行3个以上的进程。 / p>
在脚本开始时,前3个进程开始。
5分钟后:第一个过程结束,第四个过程开始。
第10分钟:第2和第4个过程结束,第5个过程开始。
第15分钟:第3个过程结束。
第20分钟:第5个过程结束。第6个过程在没有进一步等待的情况下被杀死。我在stackoverflow上做了很多研究,但我找不到类似的用例:
https://www.codeword.xyz/2015/09/02/three-ways-to-script-processes-in-parallel/
http://www.gnu.org/software/parallel/
感谢任何帮助或评论。
答案 0 :(得分:2)
除非我错过了什么,否则我认为 GNU Parallel 会很容易为你做到这一点。
如果您创建一个名为jobs
的文件,其中包含:
./my-process-1 --args1 && ./my-process-2 --args1
./my-process-1 --args2 && ./my-process-2 --args2
./my-process-1 --args3 && ./my-process-2 --args3
./my-process-1 --args4 && ./my-process-2 --args4
./my-process-1 --args5 && ./my-process-2 --args5
./my-process-1 --args6 && ./my-process-2 --args6
然后你可以看到 GNU Parallel 将使用--dry-run
做什么,如下所示:
parallel --dry-run -j 3 -k -a jobs
<强>输出强>
./my-process-1 --args1 && ./my-process-2 --args1
./my-process-1 --args2 && ./my-process-2 --args2
./my-process-1 --args3 && ./my-process-2 --args3
./my-process-1 --args4 && ./my-process-2 --args4
./my-process-1 --args5 && ./my-process-2 --args5
./my-process-1 --args6 && ./my-process-2 --args6
如果my-process-1
需要3秒而my-process-2
需要5秒,则整数需要16秒,因为前3行是并行执行的,每行需要8秒,然后接下来的3行是并行执行并再花8秒。
答案 1 :(得分:1)
你可以用xargs做到这一点。例如,下面将使用3个并行进程为参数3,3,4,1,4和15运行函数“func”6次,并在10秒后终止它:
function func { echo args:$1; sleep $1; echo done; }
export -f func
function worktodo { echo -e 3\\n 3\\n 4\\n 1\\n 4\\n 15 | xargs -P 3 -I {} sh -c 'func "$@"' _ {}; }
export -f worktodo
timeout 10 sh -c "worktodo" || echo "timeout"
答案 2 :(得分:1)
这是一个骨架,使用SIGINT
在父级和子进程之间进行通信。
设置一个陷阱来计算忙碌的进程数量,当一个进程结束时,启动另一个进程:
trap '{ let Trapped++; }' INT # start another child
将其初始化为您希望并行运行的数量:
Trapped=$ATONCE # 3 in your case
然后根据需要循环并启动子项:
while true
do
# Assuming there's more work to do. You need to decide when to terminate
do_work &
while [ $Trapped -le 0 ]
wait # race condition, interruptible by SIGINT
local rc=$? # ...
done
done
然后在do_work
中,您需要以下内容:
call-external-process with parms
# Deal with problems
[[ $? -ne 0 ]] && { .... }
# Now tell parent we're done
kill -INT $$
这是一个粗略的想法。缺少的是你如何知道什么时候你没有更多的流程可以启动,它需要更好的错误处理,但希望你能得到这个想法。将会有3个进程一直在运行,一个进程在结束时启动,直到没有什么可做的。