8

Контекст:

Пользователи предоставляют мне свои собственные скрипты для запуска. Эти сценарии могут быть любого типа, такие как сценарии для запуска нескольких программ с графическим интерфейсом, внутренних служб. Я не контролирую, как пишутся сценарии. Эти сценарии могут быть блокирующего типа, т.е. выполнение ожидает завершения всех дочерних процессов (программ, запускаемых последовательно)

#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 всех дочерних процессов, созданных при выполнении сценария? Любые указатели или подсказки будут высоко оценены

2 ответа2

5

Чтобы ответить на ваш вопрос напрямую, команда

jobs -p

дает вам список всех дочерних процессов.

Альтернатива № 1

Но в вашем случае может быть проще использовать команду wait без каких-либо параметров:

first_program &
second_program &
wait

Это будет ждать, пока ВСЕ дочерние процессы не завершатся.

Альтернатива № 2

Другая альтернатива - использование $! чтобы получить PID последней программы и, возможно, накопить в переменной, например, так:

pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"

и затем используйте wait с этим (это в том случае, если вы хотите подождать только часть ваших дочерних процессов):

wait $pids

Альтернатива № 3

ИЛИ, если вы хотите подождать, пока ЛЮБОЙ процесс не завершится, вы можете использовать

wait -n $pids

Информация о бонусе

Если вы хотите, чтобы сигнатура в вашем bash-скрипте также закрывала ваши дочерние процессы, вам нужно будет распространить сигнал примерно так (поместите это где-то вверху, перед началом любого процесса):

trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT
1

Спасибо, ребята за ваши ответы .. Я получил решение на стеке потока

Вы можете использовать wait, чтобы дождаться завершения всех фоновых процессов, запущенных usercript. Поскольку wait работает только для дочерних элементов текущей оболочки, вам нужно будет использовать их сценарий вместо того, чтобы запускать его как отдельный процесс.

(источник usercript; подождите)

Подбор сценария в явной подоболочке должен достаточно близко имитировать запуск нового процесса. Если нет, вы также можете создать фоновую подоболочку, которая заставляет запускать новый процесс, а затем дождаться его завершения.

(источник usercript; ждать) и ждать

Вот ссылка на оригинальный ответ @chepner: https://stackoverflow.com/questions/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .