Если kill -9 не работает, значит SIGKILL вообще не дошёл до живого процесса: он уже зомби, застрял в ядре в непрерываемом сне, или его перезапускает супервизор с новым PID. ps -eo pid,ppid,stat,comm сразу покажет, какой из трёх случаев у вас. Вот как это прочитать и что делать с каждым.
1. Сначала понять, в каком процесс состоянии
$ clai покажи состояние процесса и что он делает→ ps -eo pid,ppid,stat,comm | awk '$3 ~ /^Z/' 339320 339308 Z sd_espeak-ng-mb1053146 902286 Z headless_shell1053147 902286 Z headless_shell
Первая буква в STAT решает всё. Z — зомби, D — непрерываемый сон, S/R — живой процесс, который просто игнорирует сигнал.
2. Обзор состояний на машине
$ clai посчитай процессы по состояниям→ ps -eo stat --no-headers | cut -c1 | sort | uniq -c | sort -rn 588 S 141 I 4 Z 1 R
Несколько зомби — норма, они ничего не занимают, кроме записи в таблице процессов. Тысячи — баг в родителе, который не вызывает wait().
3. Зомби убить нельзя — он уже мёртв
$ clai найди родителя зомби-процесса 339320→ ps -o ppid= -p 339320 339308
Зомби — это запись о завершившемся процессе, которую родитель не забрал через wait(). Слать ему сигналы бессмысленно — разбираться нужно с родителем. Когда родитель умрёт, зомби усыновит init и подчистит.
4. D-state: процесс застрял в ядре
$ clai покажи процессы в непрерываемом сне и что они ждут→ ps -eo pid,stat,wchan:20,comm | awk '$2 ~ /^D/'
D означает ожидание ввода-вывода в ядре — обычно зависшая сетевая ФС или сбойный диск. Такой процесс не принимает даже SIGKILL, потому что не выполняет код пользователя. Колонка wchan показывает, в какой функции ядра он стоит. Лечится источником: примонтировать NFS обратно, заменить диск. Иногда помогает только перезагрузка.
5. Процесс жив, но его перезапускают
$ clai проверь, не перезапускает ли systemd этот сервис после убийства→ systemctl show -p Restart -p RestartUSec app.service
Если процесс возрождается с новым PID, вы боретесь не с ним, а с супервизором. Останавливать нужно через systemctl stop, а не kill.
6. Корректная последовательность
$ clai аккуратно останови процесс 12345, а если не выйдет через 5 секунд — принудительно→ kill 12345; sleep 5; kill -0 12345 2>/dev/null && kill -9 12345
Сначала SIGTERM, чтобы процесс закрыл файлы и сбросил буферы. kill -0 не убивает, а только проверяет, жив ли ещё процесс. SIGKILL — последнее средство: после него данные в буферах теряются.
Грабли
- kill -9 не доходит до процесса, а обрабатывается ядром. Именно поэтому он бессилен против D-state: там просто некому его обработать, процесс не исполняет свой код.
- Зомби не занимает ни память, ни CPU. Он занимает запись в таблице процессов и строчку в
ps. Паниковать из-за трёх зомби не нужно — это симптом, а не проблема. - SIGKILL не даёт процессу закрыться корректно. Незаписанные буферы теряются, блокировки остаются. Для баз данных и файловых серверов это реальный риск повреждения данных.
Похожие вопросы
Почему kill -9 не работает? Три причины: процесс уже зомби (мёртв, убивать нечего), процесс в D-state (не исполняет пользовательский код), либо его перезапускает супервизор.
Как убить все зомби разом? Никак напрямую. Найдите родителей через ps -eo ppid,stat | awk '$2 ~ /^Z/' и перезапустите их — либо дождитесь, пока они сами вызовут wait().
Нужна ли перезагрузка при D-state? Часто нет. Сначала устраните причину ожидания: восстановите сетевую ФС, проверьте dmesg на ошибки диска. Перезагрузка — если источник недоступен.
Читайте также
- "Убить процесс на порту 8080" — и другое, что вы вечно гуглите
- Найти процесс, память которого постоянно растёт
- "Кто ест мой CPU прямо сейчас?"
CliAI не починит застрявший поток в ядре, но избавит от подбора флагов ps и awk в два часа ночи. Установите одной строкой.