¿Ejecutar un comando bash después de algunos comandos simultáneos?

13

Quiero ejecutar algunos comandos en paralelo. Cuando todos estos comandos hayan terminado, comience el siguiente. Pensé que el siguiente enfoque funcionará

#!/bin/bash
command1 &
command2 &
command3 &&
command4

Pero no fue así. Necesito funcionar command4cuando todos los primeros tres comandos han sido completamente terminado.

Googlebot
fuente

Respuestas:

28
#!/bin/bash
command1 &
command2 &
command3 &

wait
command4

wait (sin ningún argumento) esperará hasta que todos los procesos en segundo plano hayan salido.

La descripción completa de waiten el bashmanual:

wait [-n] [n ...]

Espere a cada proceso secundario especificado y devuelva su estado de finalización. Cada uno npuede ser un ID de proceso o una especificación de trabajo; Si se proporciona una especificación de trabajo, se esperan todos los procesos en la tubería de ese trabajo. Si nno se proporciona, se esperan todos los procesos secundarios actualmente activos y el estado de retorno es cero. Si -nse proporciona la opción, waitespera a que finalice cualquier trabajo y devuelve su estado de salida. Si nespecifica un proceso o trabajo inexistente, el estado de retorno es 127. De lo contrario, el estado de retorno es el estado de salida del último proceso o trabajo esperado.

Kusalananda
fuente
1
Otra opción es guardar el PID de cada niño usando algo como PID1=$!y luego esperarlos a todos wait "$PID1" "$PID2" "$PID3". Eso es un poco más complicado, pero funcionará si el proceso tiene otros hijos a los que no desea esperar.
kasperd
1
@kasperd Mejor con una matriz en ese caso: cmd1 & pids=( $! ); cmd2 & pids+=( $! ); cmd3 & pids+=( $! ); wait "${pids[@]}"o algo similar.
Kusalananda
@kasperd Por "mejor" quiero decir "usa solo una variable". No hay nada inherentemente malo en usar muchos, y probablemente sea totalmente correcto para casos pequeños como este.
Kusalananda
0

Me gusta la waitrespuesta, pero solo como ejercicio académico, creo que esto también funcionaría:

bash -c 'command1 & command2 & command3 &' && command4

Por favor, corríjame si estoy equivocado.

hamburguesa
fuente
2
¿Probaste esto? Absolutamente no funciona. Ejemplo: time bash -c "sleep 5 &sleep 5 &sleep 5 &" && echo foo si no dice que el comando bash tardó cinco segundos, no hizo lo que deseaba.
Seth Robertson
Lo probé con sueño y ecos y parecía funcionar. Su ejemplo demuestra lo contrario.
hamburguesa