Executar um comando bash após alguns comandos simultâneos?

13

Eu quero executar alguns comandos em paralelo. Quando todos esses comandos estiverem concluídos, inicie o próximo. Embora a seguinte abordagem funcione

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

mas não fez. Preciso executar command4quando todos os três primeiros comandos estiverem completamente concluídos.

Googlebot
fonte

Respostas:

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

wait
command4

wait (sem argumentos) aguardará até que todos os processos em segundo plano sejam encerrados.

A descrição completa waitdo bashmanual:

wait [-n] [n ...]

Aguarde cada processo filho especificado e retorne seu status de encerramento. Cada um npode ser um ID de processo ou uma especificação de trabalho; se uma especificação de trabalho for fornecida, todos os processos no pipeline desse trabalho serão aguardados. Se nnão for fornecido, todos os processos filhos ativos no momento são aguardados e o status de retorno é zero. Se a -nopção for fornecida, waitaguarde o término de qualquer trabalho e retorne seu status de saída. Se nespecificar um processo ou trabalho inexistente, o status de retorno será 127. Caso contrário, o status de retorno será o status de saída do último processo ou trabalho aguardado.

Kusalananda
fonte
1
Outra opção é salvar o PID de cada criança usando algo como PID1=$!e, em seguida, esperar por todas elas wait "$PID1" "$PID2" "$PID3". Isso é um pouco mais complicado, mas funcionará se o processo tiver outros filhos pelos quais você não deseja esperar.
Kasperd #
1
@ Kasperd Melhor com uma matriz nesse caso: cmd1 & pids=( $! ); cmd2 & pids+=( $! ); cmd3 & pids+=( $! ); wait "${pids[@]}"ou algo semelhante.
Kusalananda
@kasperd Por "melhor", quero dizer "usa apenas uma variável". Nada inerentemente errado com o uso de muitos, e provavelmente é totalmente aceitável para casos pequenos como este.
Kusalananda
0

Eu gosto da waitresposta, mas apenas como um exercício acadêmico, acho que isso também funcionaria:

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

Por favor corrija-me se eu estiver errado.

hamburguer
fonte
2
Você testou isso? Absolutamente não funciona. Exemplo: time bash -c "sleep 5 &sleep 5 &sleep 5 &" && echo foo se ele não disser que o comando bash levou cinco segundos, não fez o que você deseja.
Seth Robertson
Eu testei com sono e ecos e parecia funcionar. Seu exemplo prova o contrário.
Burger