Обробляють нащадків


20

Я намагаюся створити контейнер для процесів. Контейнер запустить інші програми. Наприклад - bash-скрипт, який запускає запущені фонові завдання із використанням '&'.

Важливою особливістю, яку я переслідую, є така: коли я вбиваю контейнер, все, що було породжене під ним, повинно бути вбито. Не просто спрямовують дітей, а й їхніх нащадків.

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

Я вірю в те, що я хочу досягти, бо коли ви закриваєте xterm, все, що працює в ньому, вбивається, якщо тільки це не було nohup'd. Сюди входять сиротні процеси. Це те, що я хочу відтворити.

У мене є ідея, що те, що я шукаю, включає сесії Unix.

Якщо був би надійний спосіб ідентифікувати всіх нащадків процесу, було б корисно мати можливість і надсилати їм довільні сигнали. наприклад SIGUSR1.


Ну, вбивство батьківського процесу посилає SIGHUPна це прямі дитячі процеси. За замовчуванням обробник сигналу відключення припиняє виконання процесу, тому за замовчуванням маршрут вбиває всіх нащадків. Детальніше про процеси та групи процесів.
alex

Закриття xterm вбиває все, що виникло в xterm, оскільки TTY знищений. Якщо ви можете придумати спосіб створити tty, який можуть використовувати дочірні процеси, ви можете знищити TTY і виконати те саме. Будь-який процес, який не закрив, що TTY (нохуп та друзі), отримає ЗАРАЗ.
Патрік

Відповіді:


23

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

Однак існують способи вбити більше ніж один процес. Але ви не надсилатимете сигнал одному процесу. Ви можете вбити цілу групу процесів , відправивши сигнал до -1234, де 1234 є PGID (ідентифікатор групи процесів), який є PID лідера групи процесів. Під час запуску конвеєра весь конвеєр починається як група процесів (програми можуть змінити це за допомогою виклику setpgidабо setpgrp).

Коли ви запускаєте процеси у фоновому режимі ( foo &), вони знаходяться у власній групі процесів. Групи процесів використовуються для управління доступом до терміналу; Зазвичай лише група процесу переднього плану має доступ до терміналу. Фонові завдання залишаються в одному сеансі , але немає можливості знищити цілий сеанс або навіть перерахувати групи сеансів або процеси в сеансі, так що це не дуже допоможе.

Коли ви закриваєте термінал, ядро ​​посилає сигнал SIGHUPвсім процесам, які мають його як контрольний термінал . Ці процеси утворюють сеанс , але не всі сесії мають контрольний термінал. Отже, для вашого проекту є одна можливість запустити всі процеси у своєму власному терміналі, створеному сценарієм , екраном тощо setsid.

Ви можете забезпечити більшу ізоляцію, запустивши процеси як власний користувач, який нічого іншого не робить. Тоді легко вбити всі процеси: запустити kill( системний виклик або утиліту ) як цього користувача і використовувати -1 як PID-аргумент для вбивства, що означає "всі процеси цього користувача".

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


Якщо ви програмуєте власні процеси, то ви можете використовувати щось таке, як:, prctl(PR_SET_PDEATHSIG, SIGHUP);докладніша інформація: man7.org/linux/man-pages/man2/prctl.2.html
Alexis Wilke

Жил, ти згадуєш про це - "Коли ви закриваєте термінал, ядро ​​надсилає сигнал SIGHUP всім процесам, які мають його як контрольний термінал". Після цього я вважаю, що термінал надсилає SIGHUP до лідера сеансу (оболонки), який передає його всім групам процесів протягом сеансу. Хто з двох буде правильним?
iruvar

4

У батьківському сценарії потрапляє в пастку сигнал вбивства, і він вбиває всіх дітей. Наприклад,

#!/bin/bash
# kill the parent and children together
trap "kill 0" EXIT
# create all the children
for n in $(seq 1 100)
do
    ( echo "begin $n"; sleep 60; echo "end $n" ) &
done
# wait for the children to complete
wait

2

Надійним способом ідентифікації всіх нащадків процесу є використання команди, pstree <pid>де pid - ідентифікатор вашого батьківського процесу.

Прочитайте сторінку людини pstree тут .

Щоб сигналізувати всім членам групи процесів: killpg(<pgrp>, <sig>);
де pgrp - це номер групи процесу, а сиг - сигнал.

Щоб чекати дітей у визначеній групі процесів: waitpid(-<pgrp>, &status, ...);

Альтернативою тому, що ви робите, є запустити контейнер процесу в новій оболонці bash. Створіть нову оболонку bash за допомогою команди bashта запустіть ваші процеси. Коли ви хочете, щоб усі процеси були закінчені, вийдіть з оболонки командою exit.


Я думаю, що killpg дозволить мені робити те, що мені потрібно зробити. Спасибі.
Крейг Тернер

1

Використовуйте

unshare -fp --kill-child -- yourprogram

Якщо ви вб'єте unshare, всі дочірні процеси (які, yourprogramможливо, породили), будуть вбиті.

Тепер це можливо за допомогою util-linux 2.32; Я реалізував це вище за течією . Для цього потрібні або простори імен користувачів (параметр налаштування ядра CONFIG_USER_NS=y), або кореневі привілеї. Дивіться також тут .


0

RKill команди з PsList пакета посилає даний сигнал (або SIGTERMза замовчуванням) для зазначеного процесу і всіх його нащадків:

rkill [-SIG] pid/name...

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