简体   繁体   English

重击,同时运行多个命令,等待N完成再生成更多

[英]Bash, run multiple commands simultaneously, wait for N to finish before spawning more

Alright, so I've tried gnu parallel and there's some quirks about getting that to work that makes it not possible for me to use. 好吧,所以我尝试了gnu parallel,并且有一些使它无法正常工作的怪癖。

Ultimately I'd love to just be able to do something like this: 最终,我希望能够做这样的事情:

for modelplot in /${rfolder}/${mplotsfolder}/${mname}/$mscript.gs
do

for regionplot in $mregions
do
opengrads -bclx "${modelplot}.gs $regionplot ${plotimage} ${date} ${run} ${gribfile} ${modelplot}" && wait -n
done

done

But I can't seem to find a way to limit the spawning of background processes to a specific number. 但是我似乎找不到一种方法来将后台进程的产生限制为特定数量。 Someone mentioned doing: 有人提到这样做:

for i in {1..10}; do echo "${i} & (( count ++ > 5 )) && wait -n; done

Should do it, but I can't really verify if it is working that way. 应该这样做,但我无法真正验证它是否以这种方式工作。 It seems like it just spawns them all instantly. 似乎只是立即将它们全部生成。 I'm assuming the output in terminal of that should be: echo 1, echo 2, echo 3, echo 4, echo 5. Then echo 6, echo 7, echo 8, echo 9, echo 10. 我假设终端的输出应为:回声1,回声2,回声3,回声4,回声5。然后回声6,回声7,回声8,回声9,回声10。

I'm just trying to spawn, say 5, iterations of a loop, wait for those to finish and then spawn the next 5, wait for those to finish, spawn the next 5, etc until the loop is done. 我只是想产生一个循环的5次迭代,等待它们完成,然后产生下一个5,等待它们完成,产生下一个5,依此类推,直到循环完成。

Each time you start a background job, increment a count. 每次启动后台作业时,都要增加一个计数。 When that count reaches 5 (or whatever), wait for all background jobs to complete, then reset the count to 0 and resume starting background jobs. 当该计数达到5(或其他数值)时,请wait所有后台作业完成,然后将计数重置为0并恢复开始后台作业。

p_count=0
for modelplot in /${rfolder}/${mplotsfolder}/${mname}/$mscript.gs; do
  for regionplot in $mregions; do
      opengrads -bclx "${modelplot}.gs $regionplot ${plotimage} ${date} ${run} ${gribfile} ${modelplot}" &
      if (( ++p_count == 5 )); then
          wait
          p_count=0
      fi
    done
  done
done

It is surprisingly tricky to keep exactly 5, rather than at most 5, jobs running in the background in shell. 在Shell中将5个作业(而不是最多5个)保持在后台运行是非常棘手的。 ( wait -n lets you know when a job has finished, but not how many have finished.) To keep the machine busy, a tool like xargs or parallel is more appropriate. wait -n让你知道当一个工作已完成,但不会有多少人完成)。为了保持机器忙,像一个工具xargsparallel是比较合适的。

From your comments it is pretty unclear what you want. 从您的评论中还不清楚您想要什么。

But using the {= =} construct you can get almost anything in the arguments. 但是,使用{= =}构造可以在参数中获得几乎所有内容。

Append .gs only on the first run: 仅在首次运行时附加.gs:

parallel echo {}'{= if($job->seq() == 1) { $_ = ".gs" } else { $_="" } =}' ::: a b c

Append .gs only on the last run: 仅在上一次运行时附加.gs:

parallel echo {}'{= if($job->seq() == $Global::JobQueue->total_jobs() ) { $_ = ".gs" } else { $_="" } =}' ::: a b c

Disregarding the comments and looking only at the loop in the question the solution is: 忽略注释,仅查看问题中的循环,解决方案是:

parallel --header : opengrads -bclx "{modelplot}.gs {regionplot} ${plotimage} ${date} ${run} ${gribfile} {modelplot}" ::: modelplot /${rfolder}/${mplotsfolder}/${mname}/$mscript.gs ::: regionplot $mregions

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM