我需要一个bash脚本来在后台运行一些作业,一次三个作业。
我知道可以通过以下方式做到这一点,为了说明,我假设工作的数量是6:
./j1 &
./j2 &
./j3 &
wait
./j4 &
./j5 &
./j6 &
wait
然而,这样一来,例如,如果j2运行j1和j3需要更长的时间,那么,我将只会遇到一个运行很长时间的后台作业。
备选方案(这就是我想要的)是每当一个作业完成时,bash应该开始队列中的下一个作业,以便在任何给定时间保持3个作业的速率。是否可以编写一个bash脚本来实现这个替代方案,可能使用循环?请注意,我需要运行更多的工作,我希望这种替代方法可以节省很多时间。
这是我的脚本草稿,我希望你可以帮助我验证它的正确性并改进它,因为我是bash脚本的新手。此脚本中的提示是从here,here和here获取和修改的:
for i in $(seq 6)
do
# wait here if the number of jobs is 3 (or more)
while (( (( $(jobs -p | wc -l) )) >= 3 ))
do
sleep 5 # check again after 5 seconds
done
jobs -x ./j$i &
done
wait
恕我直言,我认为这个脚本会执行所需的行为。但是,我需要知道 - 来自bash专家 - 如果我做错了什么或者是否有更好的方法来实现这个想法。
非常感谢你。
答案 0 :(得分:4)
使用GNU xargs:
printf '%s\0' j{1..6} | xargs -0 -n1 -P3 sh -c './"$1"' _
使用bash(4.x)内置:
max_jobs=3; cur_jobs=0
for ((i=0; i<6; i++)); do
# If true, wait until the next background job finishes to continue.
((cur_jobs >= max_jobs)) && wait -n
# Increment the current number of jobs running.
./j"$i" & ((++cur_jobs))
done
wait
请注意,依赖于builtins的方法有一些极端情况 - 如果您在同一时间有多个作业退出,则单个wait -n
可以获得其中几个,从而有效地消耗多个插槽。如果我们想要更强大,我们最终可能会得到以下内容:
max_jobs=3
declare -A cur_jobs=( ) # build an associative array w/ PIDs of jobs we started
for ((i=0; i<6; i++)); do
if (( ${#cur_jobs[@]} >= max_jobs )); then
wait -n # wait for at least one job to exit
# ...and then remove any jobs that aren't running from the table
for pid in "${!cur_jobs[@]}"; do
kill -0 "$pid" 2>/dev/null && unset cur_jobs[$pid]
done
fi
./j"$i" & cur_jobs[$!]=1
done
wait
......这显然是很多工作,但仍然有一个小的种族。请考虑使用xargs -P
。 :)
答案 1 :(得分:3)
使用GNU Parallel:
mask = (a > 3) & (b > 8)
c[mask] += b[mask]*2
或者如果你的shell不做..扩展(例如csh):
parallel -j3 ::: ./j{1..6}
如果您认为无法安装GNU Parallel,请阅读http://oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html并对无法安装的原因发表评论。
答案 2 :(得分:0)
也许这可以帮助..
示例用例:运行&#39;睡眠20&#39; 30次,仅作为一个例子。它可以是任何工作或其他脚本。我们的控制逻辑是检查&#34;已经解雇了多少?&#34;小于或等于&#34;在一个while循环中定义的最大进程#34;如果没有,请开一个,如果是,则睡5秒钟。
脚本输出:在下面的片段中,我们观察到现在我们已经睡了20&#39;我们配置max = 30。
max=$(cat max.txt)
更改no的值。运行时的作业:脚本有一个参数&#34; max&#34;,它从文件&#34; max.txt&#34;(max.txt
)获取值,然后将其应用于while循环的每次迭代。如下所示,我们将其更改为45,现在我们有45&amp; 39; 20&#39;在后台运行的命令。您可以将主脚本放在后台,只需不断更改&#34; %_Host@User> cat > max.txt
45
^C
%_Host@User> ps -ef|grep 'sleep 20'|grep -v grep|wc -l
45
%_Host@User>
&#34;控制。
#!/bin/bash
#---------------------------------------------------------------------#
proc='sleep 20' # Your process or script or anything..
max=$(cat max.txt) # configure how many jobs do you want
curr=0
#---------------------------------------------------------------------#
while true
do
curr=$(ps -ef|grep "$proc"|grep -v grep|wc -l); max=$(cat max.txt)
while [[ $curr -lt $max ]]
do
${proc} & # Sending process to background.
max=$(cat max.txt) # After sending one job, again calculate max and curr
curr=$(ps -ef|grep "$proc"|grep -v grep|wc -l)
done
sleep .5 # sleep .5 seconds if reached max jobs.
done
#---------------------------------------------------------------------#
<强>脚本:强>
final
让我们知道它是否有用。