Сигналы и завершение процессов: TERM, KILL и корректная остановка
Сигнал — асинхронное уведомление процессу от ядра или другого процесса. Он может попросить приложение перечитать конфигурацию, остановиться, продолжить работу или завершиться. Сигнал не равен гарантированной «команде»: процесс может обработать некоторые сигналы, заблокировать их или уже исчезнуть.
Начинайте с SIGTERM
kill PID без флага отправляет SIGTERM. Это запрос на корректное завершение: приложение может перестать принимать новые запросы, закончить текущую запись, закрыть сокеты и удалить временные файлы.
sleep 300 &
pid=$!
kill -TERM "$pid"
wait "$pid"
printf 'wait status=%s\n' "$?"wait связывает наблюдение с конкретным дочерним PID. Проверка только через ps может попасть в момент до завершения или увидеть уже переиспользованный номер.
Обработчик и cleanup
Bash-скрипт может поставить trap. Обработчик должен быть коротким и идемпотентным: второй сигнал не должен разрушать уже начатую очистку.
tmp_dir=$(mktemp -d)
cleanup() {
rm -r -- "$tmp_dir"
}
trap cleanup EXIT
trap 'exit 143' TERM
printf 'working in %s\n' "$tmp_dir"Trap на EXIT выполняется и при обычном завершении. В production временный каталог лучше создавать на подходящем filesystem и удалять только после проверки непустого ожидаемого префикса.
SIGKILL — крайняя мера
SIGKILL нельзя перехватить, заблокировать или проигнорировать. Ядро прекращает выполнение немедленно, поэтому приложение не делает cleanup. kill -KILL оправдан, когда процесс после разумного timeout не отвечает на TERM и подтверждён его PID. Он не исправляет непрерываемое ожидание D: такой процесс завершится только когда вернётся из операции ядра.
Для группы процессов service manager надёжнее управлять unit, чем посылать сигнал одному случайному worker. Иначе supervisor может сразу запустить замену.
Ошибка и диагностика
Опасная ошибка — pkill -f app с широким pattern. Сначала выполните pgrep -a -f 'pattern', подтвердите пользователей, parent и число кандидатов. После TERM наблюдайте status service, журналы и timeout. Если понадобился KILL, сохраните причину зависания: stack, state, открытые файлы или хотя бы последние логи до уничтожения процесса.
Практика
Создайте Bash-скрипт с временным файлом и trap на EXIT/TERM. Запустите его в фоне, отправьте TERM и проверьте удаление файла. Затем повторите с KILL и объясните, почему cleanup не выполнился. Удалите оставшийся fixture вручную по точному пути.
Что важно запомнить
- TERM оставляет приложению возможность корректно завершить работу; KILL — нет.
- Перед сигналом подтвердите identity процесса, а после — наблюдайте фактическое состояние.
- Supervisor или systemd unit нужно останавливать через управляющий слой, иначе процесс может возродиться.