Контекст:
Пользователи предоставляют мне свои собственные скрипты для запуска. Эти сценарии могут быть любого типа, такие как сценарии для запуска нескольких программ с графическим интерфейсом, внутренних служб. Я не контролирую, как пишутся сценарии. Эти сценарии могут быть блокирующего типа, т.е. выполнение ожидает завершения всех дочерних процессов (программ, запускаемых последовательно)
#exaple of blocking script
echo "START"
first_program
second_program
echo "DONE"
или не блокирующий тип, то есть те, которые обрабатывают дочерний процесс в фоновом режиме и выходят что-то вроде
#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"
Чего я пытаюсь достичь?
Предоставляемые пользователем сценарии могут быть любого из двух указанных выше типов или сочетанием обоих. Моя задача - запустить скрипт и подождать, пока все запущенные им процессы не завершатся, а затем завершить работу узла. Если это блокирующий тип, то дело простое, т.е. получите PID процесса выполнения скрипта и подождите, пока ps -ef | grep -ef PID больше не будет иметь записей. Неблокирующие скрипты доставляют мне неприятности
Есть ли способ получить список PID всех дочерних процессов, созданных при выполнении сценария? Любые указатели или подсказки будут высоко оценены
pid$(foo.sh; echo $!)
что даст вам PID, которыйfoo.sh
вы затем сможете использоватьps --ppid
. Будет ли это работать?grep
, простоps –udummy_user
. Также посмотрите на группы процессов.ps
без аргументов (должно быть толькоbash
иps
в начале). Начните свой сценарий там. После того, как он закончится, подождите, пока неps | wc -l
достигнете ожидаемого значения.Ответы:
Чтобы ответить на ваш вопрос напрямую, команда
дает вам список всех дочерних процессов.
Альтернатива № 1
Но в вашем случае может быть проще использовать команду
wait
без каких-либо параметров:Это будет ждать, пока ВСЕ дочерние процессы не завершатся.
Альтернатива № 2
Другой альтернативой является использование
$!
для получения PID последней программы и, возможно, накопления в переменной, например так:и затем используйте wait с этим (это в том случае, если вы хотите подождать только часть ваших дочерних процессов):
Альтернатива № 3
ИЛИ, если вы хотите подождать, пока ЛЮБОЙ процесс не завершится, вы можете использовать
Информация о бонусе
Если вы хотите, чтобы сигнатура в вашем bash-скрипте также закрывала ваши дочерние процессы, вам нужно будет распространить сигнал примерно так (поместите это где-нибудь вверху, перед началом любого процесса):
источник
Спасибо, ребята, за ваши ответы .. Я получил решение по stackoverflow
Вы можете использовать wait, чтобы дождаться завершения всех фоновых процессов, запущенных usercript. Поскольку wait работает только для дочерних элементов текущей оболочки, вам нужно будет использовать их сценарий вместо того, чтобы запускать его как отдельный процесс.
(источник usercript; подождите)
Подбор сценария в явной подоболочке должен достаточно близко имитировать запуск нового процесса. Если нет, вы также можете создать фоновую подоболочку, которая заставляет запускать новый процесс, а затем дождаться его завершения.
(источник usercript; ждать) и ждать
Вот ссылка на оригинальный ответ @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969
источник
wait
Затем ваша команда будет ждать детей usercript, но не своих внуков.