linux - bash 脚本在后台运行固定数量的作业

标签 linux bash shell

我需要一个 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 专家那里知道我是否做错了什么,或者是否有更好的方法来实现这个想法。

非常感谢。

最佳答案

使用 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

请注意,依赖内置函数的方法有一些极端情况——如果您有多个作业同时退出,单个 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。 :)

关于linux - bash 脚本在后台运行固定数量的作业,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42211173/

相关文章:

shell - fish shell : filter $argv (lightweight/dynamic argparse)

c++ - 按升序从消息队列中读取数据

linux - 具有不同内核的 D​​ocker

linux - 如何查找特定文件

bash - 如何删除远程机器上 authorized_keys 文件中的重复行

bash - Shell脚本将文件中的十六进制值转换为十进制

linux - 使用 vlc 命令行和 html5 从 ubuntu linux 上的模拟电视卡将电视直播到 ipad 1 或 2

windows - 在 Windows 上的 bash 中清除 PowerShell 控制台

bash - 将多个参数传递给 shell 脚本并解析它们

shell - 为什么shell使用0作为成功?