wait - это команда, которая ожидает завершения заданных заданий и возвращает статус выхода из ожидаемой команды.
Поскольку команда wait влияет на текущую среду выполнения оболочки, она реализована как встроенная команда в большинстве оболочек.
В этой статье мы рассмотрим встроенную команду wait в Bash.
Команда Bash wait
Общий синтаксис встроенной команды wait имеет следующий вид:
1 | wait [options] ID |
ID - это идентификатор процесса или задания. Если ID не указан, команда ждет, пока не завершатся все дочерние фоновые задания.
Команда wait возвращает статус завершения последней ожидаемой команды.
Например, чтобы дождаться фонового процесса с PID 7651, нужно использовать:
1 | wait 7651 |
Если задано несколько процессов, команда ожидает завершения всех процессов.
Задания задаются с помощью спецификации задания ("jobspec"), которая представляет собой способ обозначения процессов, составляющих задание. Спецификация задания начинается с символа процента, за которым следует номер задания (%n). Вот пример:
Запустите команду в фоновом режиме :
1 | rsync -a /home /tmp/home & |
Идентификатор задания оболочки (окруженный скобками) и идентификатор процесса будут отображены на вашем терминале:
1 | [2] 54374 |
Чтобы дождаться выполнения задания, выполните команду wait, за которой следует спецификация задания:
1 | wait %2 |
При вызове с опцией -n команда wait ожидает завершения только одного задания из заданных pids или jobspecs и возвращает статус завершения. Если аргументы не указаны, wait -n ожидает завершения любого фонового задания и возвращает статус завершения задания.
1 | wait -n 45431 54344 76575 |
В приведенном выше примере wait -n печатает только статус возврата задания, которое завершается первым; он не показывает PID задания. Если вы хотите получить pid задания или jobspec, для которого возвращается статус выхода, используйте опцию -p, чтобы присвоить его переменной:
1 | wait -p job_id -n 45431 54345 76572 |
- Опция -p была введена в Bash 5.1. Если вы используете более старую версию Bash, вы получите ошибку "invalid option".
- Опция -f указывает wait дождаться фактического завершения каждого pid или jobspec, прежде чем возвращать код завершения, а не возвращаться при изменении статуса задания. Эта опция действительна только при включенном контроле заданий. По умолчанию контроль заданий включен только для интерактивных подсказок.
Примеры
wait обычно используется в сценариях оболочки, порождающих дочерние процессы, которые выполняются параллельно.
Чтобы проиллюстрировать работу команды, создайте следующий сценарий:
1 2 3 4 5 6 | #!/bin/bash sleep 30 & process_id=$! echo "PID: $process_id" wait $process_id echo "Статус выхода: $?" |
Давайте объясним код построчно:
- Первая строка называется shebang и указывает операционной системе, какой интерпретатор использовать для разбора остальной части файла.
- Мы используем команду sleep для эмуляции фонового процесса, отнимающего много времени.
- $! - это внутренняя переменная Bash, которая хранит PID последнего задания, запущенного в фоновом режиме. В данном примере это PID команды sleep. Мы храним PID в переменной (process_id).
- Выводит номер PID.
- PID передается команде wait, которая ждет завершения выполнения команды sleep.
- Печатает статус выхода команды wait. $? - это внутренняя переменная Bash, в которой хранится статус выхода последней выполненной команды.
Если вы запустите сценарий, он выведет примерно следующее:
1 2 | PID: 36352 Статус выхода: 0 |
Вот пример с использованием опции -n:
1 2 3 4 5 6 7 8 | #!/bin/bash sleep 3 & sleep 30 & sleep 5 & wait -n echo "Первое задание выполнено." wait echo "Все задания выполнены". |
Когда скрипт выполняется, он порождает 3 фоновых процесса. wait -n ожидает завершения первого задания и вывода сообщения echo. wait ожидает завершения всех дочерних фоновых заданий.
1 2 | Первое задание выполнено Все задания выполнены |
Последний пример поясняет опцию -f. Откройте терминал и выполните команду:
1 2 | sleep 3600 & [1] 46672 |
Дождитесь выполнения процесса:
1 | wait 46672 |
Откройте другой терминал и остановите процесс командой kill:
1 | kill -STOP 46672 |
Как только статус процесса изменится, команда wait завершится и вернет код завершения процесса.
Теперь повторите те же шаги, но на этот раз используйте команду wait -f $pid:
1 2 | sleep 3600 & wait -f 46672 |
Остановите процесс с другого терминала:
1 | kill -STOP 46672 |
На этот раз команда wait не завершится. Она будет выполняться до тех пор, пока не завершится процесс sleep.