Есть ли в Bash встроенная функция для ожидания завершения процесса?
Команда wait
позволяет только дождаться завершения дочерних процессов. Я хотел бы знать, есть ли какой-либо способ дождаться завершения какого-либо процесса, прежде чем приступить к какому-либо сценарию.
Механический способ сделать это заключается в следующем, но я хотел бы знать, есть ли какая-либо встроенная функция в Bash.
while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done
Ответы:
Дождаться окончания любого процесса
Linux:
Дарвин (требует наличия
$pid
открытых файлов):С таймаутом (в секундах)
Linux:
Дарвин (требует наличия
$pid
открытых файлов):источник
tail
что сделает это.tail
работает под капотом путем опроса сkill(pid, SIG_0)
процессом (обнаружен с помощьюstrace
).+r 1
есть время ожидания, я лично ищу решение для MacOS, которое не использует опрос.tail
имеет линиюkill (pid, 0) != 0 && errno != EPERM
.caffeinate -w $pid
сделают свое дело.Там нет встроенных. Используйте
kill -0
в цикле для работоспособного решения:Или как более простой способ для простого однократного использования:
Как отметили несколько комментаторов, если вы хотите дождаться процессов, на которые у вас нет прав отправлять сигналы, вы найдете другой способ определить, запущен ли процесс, чтобы заменить
kill -0 $pid
вызов. В Linuxtest -d "/proc/$pid"
работает, в других системах вам, возможно, придется использоватьpgrep
(если доступно) или что-то подобноеps | grep "^$pid "
.источник
sleep 0.5
процесс с$pid
может умереть, и другой процесс может быть создан с тем же$pid
. И мы в конечном итоге ждем 2 разных процесса (или даже больше) с одинаковыми$pid
.Я обнаружил, что "kill -0" не работает, если процесс принадлежит пользователю root (или другому), поэтому я использовал pgrep и придумал:
Это могло бы иметь недостаток, заключающийся в том, чтобы соответствовать процессам зомби.
источник
kill(pid, sig=0)
завершается ошибкой, если у вызывающего процесса нет привилегии на уничтожение. Таким образом, / bin / kill -0 и «kill -0» (встроенный в bash) тоже терпят неудачу при одинаковых условиях.Этот цикл bash-скрипта заканчивается, если процесс не существует или это зомби.
EDIT : Возможно, приведенный выше сценарий был приведен ниже по Rockallite . Спасибо!
Мой оригинальный ответ ниже работает для Linux, полагаясь на
procfs
то есть/proc/
. Я не знаю его переносимость:Это не ограничивается оболочкой, но сами ОС не имеют системных вызовов для наблюдения за завершением не дочерних процессов.
источник
grep /proc/$PID/status
двойными кавычками (bash: test: argument expected
)while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do sleep 1; done
ps
, ни-p
илиs=
поддерживаютсяFreeBSD и Solaris имеют эту удобную
pwait(1)
утилиту, которая делает именно то, что вы хотите.Я считаю, что другие современные ОС также имеют необходимые системные вызовы (например, MacOS реализует BSD
kqueue
), но не все делают это доступным из командной строки.источник
> BSD and Solaris
: Проверка трех больших BSD, которые приходят на ум; ни OpenBSD, ни NetBSD не имеют этой функции (на их man-страницах), только FreeBSD, как вы можете легко проверить на man.openbsd.org .kqueue
, поэтому компиляция FreeBSDpwait(1)
будет тривиальной. Почему бы другим BSD не импортировать эту функцию, чтобы избежать меня ...plink me@oracle box -pw redacted "pwait 6998";email -b -s "It's done" etc
просто позволил мне идти домой вместо часов.Из man-страницы bash
источник
wait
без аргументов заблокирует процесс, пока не завершатся какие-либо дочерние процессы. Честно говоря, я не вижу смысла ждать какого-либо процесса, потому что всегда происходят системные процессы.sleep 1000
ctrl-z
wait [sleep pid]
возвращается немедленноВсе эти решения протестированы в Ubuntu 14.04:
Решение 1 (с помощью команды ps): просто, чтобы добавить к ответу Pierz, я бы предложил:
В этом случае
grep -vw grep
гарантирует, что grep соответствует только process_name, а не самому grep. Преимущество заключается в поддержке случаев, когда имя_процесса находится не в конце строки вps axg
.Решение 2 (с помощью команды top и имени процесса):
Замените
process_name
на имя процесса, которое отображается вtop -n 1 -b
. Пожалуйста, сохраняйте кавычки.Чтобы увидеть список процессов, которые вы ожидаете, чтобы завершить их, вы можете запустить:
Решение 3 (с помощью команды top и идентификатора процесса):
Замените
process_id
на идентификатор процесса вашей программы.источник
grep -v grep
конвейер - это массивный антипаттерн, и это предполагает, что у вас нет связанных процессов с таким же именем. Если вместо этого вам известны идентификаторы PID, это можно адаптировать к правильно работающему решению.-w
чтобы избежать проблемыgrep -v grep
в некоторой степени . Я также добавил еще два решения на основе вашего комментария.Итак, похоже, ответ - нет, встроенного инструмента нет.
После установки
/proc/sys/kernel/yama/ptrace_scope
на0
, можно использоватьstrace
программу. Другие переключатели могут быть использованы, чтобы заставить его замолчать, чтобы он действительно пассивно ожидал:источник
Operation not permitted
для второго экземпляра strace); Вы можете это подтвердить?(...)"tracee" always means "(one) thread"
(и я подтверждаю ошибку, о которой вы упоминаете). Чтобы позволить таким процессам ждать больше, вам нужно создать цепочку.Блокирующее решение
Используйте
wait
цикл in для ожидания завершения всех процессов:Эта функция будет завершена немедленно после завершения всех процессов. Это самое эффективное решение.
Неблокирующее решение
Используйте
kill -0
цикл in, чтобы дождаться завершения всех процессов + сделать что-нибудь между проверками:Время реакции уменьшилось до
sleep
времени, потому что нужно предотвратить высокую загрузку процессора.Реалистичное использование:
Ожидание завершения всех процессов + информирование пользователя обо всех запущенных PID.
Ноты
Эти функции получают PID с помощью аргументов в
$@
виде массива BASH.источник
У меня была та же проблема, я решил проблему, убив процесс и затем дождавшись завершения каждого процесса с использованием файловой системы PROC:
источник
Нет встроенной функции для ожидания завершения какого-либо процесса.
Вы можете отправлять
kill -0
на любой найденный PID, чтобы вас не озадачили зомби и другие вещи, которые все еще будут видныps
(пока вы будете получать список PID с помощьюps
).источник
Используйте inotifywait для отслеживания некоторых файлов, которые закрываются, когда ваш процесс завершается. Пример (в Linux):
-e указывает ожидаемое событие, -q означает минимальный вывод только после завершения. В этом случае это будет:
Одну команду ожидания можно использовать для ожидания нескольких процессов:
Выходная строка inotifywait сообщит вам, какой процесс завершен. Это работает только с «настоящими» файлами, а не с чем-то в / proc /
источник
В такой системе, как OSX, у вас может не быть pgrep, поэтому вы можете попробовать это приложение при поиске процессов по имени:
$
Символ в конце имени процесса гарантирует , что GREP матчи только process_name до конца строки в выходной пс , а не сам по себе.источник
/dev/null
,-q
следует использовать сgrep
. Другой случай процесса мог начаться, когда ваш цикл спал, и вы никогда не узнаете ...-q
предложение действительно, как я упомянул в своем ответе, в частности, завершающее$
средство grep не будет совпадать с именем «где-то в командной строке» и не будет совпадать с самим собой. Вы действительно пробовали это на OSX?Решение Рауно Палосаари для
Timeout in Seconds
Darwin
, является отличным обходным решением для UNIX-подобной ОС, которая не имеет GNUtail
(она не является специфической дляDarwin
). Но, в зависимости от возраста UNIX-подобной операционной системы, предлагаемая командная строка является более сложной, чем необходимо, и может дать сбой:По крайней мере на одном старом UNIX
lsof
аргумент+r 1m%s
терпит неудачу (даже для суперпользователя):Это
m%s
спецификация выходного формата. Более простой постпроцессор не требует этого. Например, следующая команда ожидает PID 5959 до пяти секунд:В этом примере, если PID 5959 выходит сам по себе до истечения пяти секунд,
${?}
это0
. Если не${?}
возвращается1
через пять секунд.Возможно, стоит прямо отметить
+r 1
, что1
это интервал опроса (в секундах), поэтому его можно изменить в соответствии с ситуацией.источник