Як отримати список усіх дочірніх процесів, породжених сценарієм


10

Контекст:

Користувачі надають мені власні сценарії для запуску. Ці сценарії можуть бути будь-якого типу, як скрипти для запуску декількох програм графічного інтерфейсу, допоміжних служб. У мене немає контролю над тим, як написані сценарії. Ці сценарії можуть бути блокувального типу, тобто виконання чекає, поки всі дочірні процеси (програми, які запускаються послідовно), вийдуть

#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 батьків. Якщо ви запускаєте сценарії, ви можете обернути їх у щось подібне, pid$(foo.sh; echo $!)що дасть вам PID, foo.shщоб потім ви могли використовувати ps --ppid. Це буде працювати?
тердон

2
Чи повинні сценарії виконуватись під UID авторського користувача? Якщо ні, то чи можете ви створити фіктивного користувача саме для цієї мети? Вам навіть не знадобиться grep, просто ps –udummy_user. Також подивіться групи процесів.
Скотт

Це скоріше спосіб вирішення, ніж рішення вашого початкового питання: Відкрийте новий сеанс баш. Ви можете перерахувати всі процеси , запущені з цієї оболонки , використовуючи psбез будь - яких аргументів (повинно бути тільки bashта psна самому початку). Почніть свій сценарій там. Закінчивши, зачекайте, поки не ps | wc -lдосягнете очікуваного значення.
Тім

Відповіді:


8

Щоб відповісти на ваше запитання безпосередньо, команда

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

Дякую, хлопці, за ваші відповіді. Я отримав рішення щодо stackoverflow

Ви можете використовувати функцію очікування, щоб дочекатися завершення всіх фонових процесів, запущених користувальницьким сценарієм. Оскільки очікування працює лише на дітей поточної оболонки, вам потрібно буде джерело їх сценарію, а не запускати його як окремий процес.

(вихідний сценарій користувача; зачекайте)

Розподіл скрипту в явній підпакеті повинен імітувати запуск нового процесу досить близько. Якщо ні, ви також можете перетворити фоновий графік, який змушує запустити новий процес, а потім дочекайтеся його завершення.

(вихідний сценарій користувача; чекати) і чекати

Ось посилання на оригінальну відповідь від @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969


3
Я також про це думав, але це рішення провалюється, коли usercript запускає підписку у фоновому режимі, яка потім запускає інший сценарій у фоновому режимі. Ваша waitкоманда буде чекати дітей userscript , але не для своїх онуків.
Тім

@Tim Щойно зрозумів, що :(
irraju
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.