Запустить команду bash после нескольких одновременных команд?

13

Я хочу запустить некоторые команды параллельно. Когда все эти команды будут завершены, начните следующую. Я думаю, что следующий подход будет работать

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

но это не так. Мне нужно запустить, command4когда все первые три команды были полностью закончены.

Googlebot
источник

Ответы:

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

wait
command4

wait (без каких-либо аргументов) будет ожидать завершения всех фоновых процессов.

Полное описание waitв bashруководстве:

wait [-n] [n ...]

Дождитесь каждого указанного дочернего процесса и верните его состояние завершения. Каждый nможет быть идентификатором процесса или спецификацией задания; если задана спецификация задания, все процессы в конвейере этого задания ожидаются. Если nне указан, то ожидаются все активные в данный момент дочерние процессы, а статус возврата равен нулю. Если -nопция указана, waitждет завершения любого задания и возвращает свой статус завершения. Если nуказан несуществующий процесс или задание, возвращаемое состояние равно 127. В противном случае возвращаемое состояние представляет собой состояние завершения последнего ожидаемого процесса или задания.

Кусалананда
источник
1
Другой вариант - сохранить PID каждого ребенка, используя что-то подобное, PID1=$!а затем подождать всех с ним wait "$PID1" "$PID2" "$PID3". Это немного сложнее, но сработает, если у процесса есть другие дети, которых вы не хотите ждать.
Касперд
1
@kasperd Лучше с массивом в этом случае: cmd1 & pids=( $! ); cmd2 & pids+=( $! ); cmd3 & pids+=( $! ); wait "${pids[@]}"или что-то подобное.
Кусалананда
@kasperd Под «лучше» я имею в виду «использует только одну переменную». Нет ничего плохого в использовании многих, и, вероятно, это вполне нормально для небольших случаев, подобных этому.
Кусалананда
0

Мне нравится waitответ, но, как академическое упражнение, я думаю, что это также сработает:

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

Пожалуйста, поправьте меня, если я ошибаюсь.

бутерброд
источник
2
Вы проверяли это? Это абсолютно не работает. Пример: time bash -c "sleep 5 &sleep 5 &sleep 5 &" && echo foo если команда bash не заняла пять секунд, она не выполняет то, что вы хотите.
Сет Робертсон
Я проверил это со сном и эхом, и это, казалось, работало. Ваш пример доказывает обратное.
бургер