script de shell: ejecute un lote de N comandos en paralelo, espere a que todos terminen, ejecute el siguiente N

9

Tarea: ejecutar bloques que consisten en 3-5 comandos (en paralelo / en segundo plano). Bloque de ejemplo:

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 &

Cuando termine, el siguiente bloque debería ejecutarse. Supongo que esto se puede hacer a través de archivos de bloqueo:

task1.sh:

real_task1 real_param1 ; rm /var/lock/myscript/task1.lock

task2.sh:

real_task2 real_param1 ; rm /var/lock/myscript/task2.lock

...

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

Aquí se pueden encontrar varios métodos para verificar si el directorio está vacío , no estoy seguro de cuál usar;

Pregunta : ¿alguna forma mejor de implementar esto?

PD Posible método de informe de estado:

 command && report_good_state.sh taskid ;  report_state_done.sh taskid; rm /var/lock/myscript/taskN.lock
kagali-san
fuente
Chicos, simplemente no sé qué decir: todas las respuestas son correctas, ¡gracias!
kagali-san

Respuestas:

8

Esto es exactamente para lo que está diseñado gnu parallel , por lo que le recomiendo que lo use. En particular, mira ejecutarlo como un semáforo :

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
Phil Hollenback
fuente
8

Tal vez alguna variación en esto?

while true
do
  ./task1.sh&
  pid1=$!
  ./task2.sh&
  pid2=$!
  ./task3.sh&
  pid3=$!
  wait $pid1
  wait $pid2
  wait $pid3
done
Eduardo Ivanec
fuente
Pero sí, GNU paralelo es mejor si está disponible.
Eduardo Ivanec
5

¿Tiene alguna razón en particular para no usar algo como GNU paralelo ? Si debe usar bash, considere métodos como los descritos en esta publicación de blog (esperar y las canalizaciones con nombre son útiles aquí).

justarobert
fuente
3

"esperar" espera a que se completen todos los trabajos en segundo plano. Muestra:

dormir 30 y dormir 40 y dormir 120 y esperar

Espera hasta que se completen todos los comandos, es decir, al menos 120 segundos para este ejemplo.

Espero que esto ayude.

Harri
fuente
0

Intentamos usar la utilidad GNU sem , como lo describió Phil Hollenback anteriormente, pero lo encontramos demasiado pesado (más de 300 instancias paralizaron la máquina). Busqué herramientas similares para implementar un semáforo de conteo ligero, pero no pude encontrar nada adecuado.

Así que implementé uno usando flock, se llama semáforo .

Tim Bunce
fuente