Запустить новую группу процессов для кода Python (с помощью утилиты setsid
) и любых других процессов (включая собственно приложение). запускается, поэтому при необходимости вы можете убить всю группу процессов.
Для этого вы можете использовать следующую конструкцию:
exec 3>&1
pgid=$(exec setsid bash -c 'echo $$; exec >&3-; exec COMMAND...')
где КОМАНДА ...
- это команда и ее параметры, которые вы обычно запускаете. Обратите внимание, что он заключен в одинарные кавычки и что запускаемая команда должна оцениваться как строка (в отличие от обычного выражения оболочки).
Первое перенаправление, 3> & 1
, копирует дескриптор стандартного вывода в дескриптор 3. Перенаправление > & 3-
перемещает дескриптор 3 в стандартный вывод.
$ (...)
выполняет ...
и оценивает данные, которые он записал на стандартный вывод.Выше мы считываем стандартный вывод в переменную оболочки pgid
.
Подоболочка ( ...
) заменяется утилитой setsid
, которая выполняет свой аргумент в новом сеансе (группе процессов). Здесь он выполняет bash
, который распечатывает PID текущего процесса ( $$
), перемещает исходный стандартный вывод из дескриптора 3 назад и заменяет себя / выполняет желаемый КОМАНДА ...
.
Оболочка будет выполнять эту строку, пока выполняется КОМАНДА ...
, и перейдет к следующей строке только после выхода самой КОМАНДА ...
.
Если КОМАНДА ...
оставляет запущенными ложные процессы, и вы хотите их убить, все, что вам нужно сделать, это запустить
kill -SIGNAL -$pgid
Вопрос в том, какой сигнал отправить. KILL
немедленно уничтожит оставшиеся процессы в группе процессов, поэтому это самый простой вариант. Однако, если процессы ведут себя нормально, вы можете попросить их выйти, послав вместо этого сигнал TERM
. Конечно, иногда процессы могут оставаться в нестабильном состоянии, чтобы они не реагировали на TERM
и их нужно было KILL
ed. Чтобы решить эту проблему, вы можете использовать небольшой цикл и ps
, чтобы увидеть, остались ли какие-либо процессы:
retries=50
while ((1)); do
# Processes left?
left=$(ps -o pid= -s $pgrp)
[ -n "$left" ] || break
# Ask them to terminate.
kill -TERM $left
# Wait 0.1 seconds.
sleep .1
# Decrement the retry counter.
((--retries > 0)) || break
done
# If there are any processes left in the group,
# send them a KILL signal.
left=$(ps -o pid= -s $pgrp)
[ -n "$left" ] && kill -KILL $left
Обратите внимание, что 50 повторных попыток (по 0,1 секунды каждая) означают, что это ждет только до 5 секунд. перед отправкой сигнала уничтожения. Это может быть неподходящим значением в зависимости от приложения и типа оборудования, на котором оно работает.Например, если машина представляет собой портативный компьютер, и приложение сохраняет некоторую историю или регистрируется в нескольких файлах, а диск оказывается в спящем режиме в точке выхода, я бы увеличил задержку, возможно, до 15–30 секунд.