Uruchomić polecenie bash po kilku jednoczesnych poleceniach?

13

Chcę uruchomić kilka poleceń równolegle. Po zakończeniu wszystkich tych poleceń uruchom następne. Myślałem, że następujące podejście zadziała

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

ale tak nie było. Muszę uruchomić, command4gdy wszystkie trzy pierwsze polecenia zostaną całkowicie zakończone.

Googlebot
źródło

Odpowiedzi:

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

wait
command4

wait (bez żadnych argumentów) poczeka, aż wszystkie procesy w tle zakończą się.

Kompletny opis waitw bashinstrukcji:

wait [-n] [n ...]

Poczekaj na każdy określony proces potomny i zwróć jego status zakończenia. Każdy nmoże być identyfikatorem procesu lub specyfikacją zadania; jeśli podano specyfikację zadania, czekane są wszystkie procesy w potoku tego zadania. Jeśli nnie zostanie podany, czekają wszystkie aktualnie aktywne procesy potomne, a zwracany status wynosi zero. Jeśli -nopcja jest podana, waitczeka na zakończenie każdego zadania i zwraca status wyjścia. Jeśli nokreśla nieistniejący proces lub zadanie, stanem zwrotnym jest 127. W przeciwnym razie stanem zwrotnym jest status zakończenia ostatniego procesu lub zadania, na które czekał.

Kusalananda
źródło
1
Inną opcją jest zapisanie PID każdego dziecka za pomocą czegoś podobnego, PID1=$!a następnie poczekanie na wszystkie z nim wait "$PID1" "$PID2" "$PID3". Jest to nieco bardziej skomplikowane, ale zadziała, jeśli proces ma inne dzieci, na które nie chcesz czekać.
kasperd
1
@kasperd Lepiej z tablicą w takim przypadku: cmd1 & pids=( $! ); cmd2 & pids+=( $! ); cmd3 & pids+=( $! ); wait "${pids[@]}"lub czymś podobnym.
Kusalananda
@kasperd Przez „lepiej” mam na myśli „używa tylko jednej zmiennej”. Nie ma z natury nic złego w korzystaniu z wielu i prawdopodobnie jest całkowicie w porządku dla takich małych przypadków.
Kusalananda
0

Podoba mi się waitodpowiedź, ale jako ćwiczenie akademickie myślę, że to też zadziała:

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

Proszę, popraw mnie jeśli się mylę.

burger
źródło
2
Testowałeś to? To absolutnie nie działa. Przykład: time bash -c "sleep 5 &sleep 5 &sleep 5 &" && echo foo jeśli nie mówi, że polecenie bash trwało pięć sekund, nie zrobiło tego, co chcesz.
Seth Robertson
Testowałem to ze snem i echem i wydawało się, że działa. Twój przykład pokazuje inaczej.
burger