shell 脚本:并行运行一批 N 个命令,等待全部完成,再运行 N 个

kag*_*san 9 bash

任务:运行由 3-5 个命令组成的块(并行/后台)。示例块:

dd if=/dev/urandom of=/mnt/1/x bs=1024 count=1024000000 &
dd if=/dev/urandom of=/mnt/2/x bs=1024 count=1024000000 &
dd if=/dev/urandom of=/mnt/3/x bs=1024 count=1024000000 &
Run Code Online (Sandbox Code Playgroud)

完成后,下一个块应该运行。我想,这可以通过锁定文件来完成:

任务1.sh:

real_task1 real_param1 ; rm /var/lock/myscript/task1.lock
Run Code Online (Sandbox Code Playgroud)

任务2.sh:

real_task2 real_param1 ; rm /var/lock/myscript/task2.lock
Run Code Online (Sandbox Code Playgroud)

...

taskgen.sh:

# loop
 # while directory isn't empty - wait...
 gen_tasks.pl # build task files from some queue
 for i in 1 2 3; do touch /var/lock/myscript/task$i.lock ; done
 ./task1.sh &
 ./task2.sh &
 ./task3.sh &
 # if task1.sh doesn't exits then exit, else loop waits for files to be deleted
Run Code Online (Sandbox Code Playgroud)

可以在这里找到许多检查目录是否为空的方法,不确定使用哪种方法;

问题:有什么更好的方法来实现这个吗?

PS 可能的状态报告方法:

 command && report_good_state.sh taskid ;  report_state_done.sh taskid; rm /var/lock/myscript/taskN.lock
Run Code Online (Sandbox Code Playgroud)

Edu*_*nec 8

也许这有一些变化?

while true
do
  ./task1.sh&
  pid1=$!
  ./task2.sh&
  pid2=$!
  ./task3.sh&
  pid3=$!
  wait $pid1
  wait $pid2
  wait $pid3
done
Run Code Online (Sandbox Code Playgroud)


Phi*_*ack 8

这正是gnu parallel的设计目的,所以我强烈建议您使用它。特别是,将其作为信号量运行:

for i in {1..4}
do
  echo running $i
  sem -j3 df dd if=/dev/urandom of=/mnt/$i/x bs=1024 count=1024000000 ";" echo done
done
# sem --wait waits until all jobs are done.
sem --wait
Run Code Online (Sandbox Code Playgroud)


jus*_*ert 5

你有什么特别的理由不使用GNU parallel 之类的东西吗?如果您必须使用 bash,请考虑使用本博客文章中描述的方法(等待和命名管道在这里很有帮助)。