При мониторинге системы Linux с помощью команды top вы можете заметить элемент в строке 'Задачи (Tasks)', например 1 зомби (zombie).
top - 16:03:19 up 7:09, 1 user, load average: 2.24, 2.21, 2.29
Задачи: 392 всего, 1 выполняется, 390 ожидает, 0 остановлено, 1 зомби
...
Что такое этот 'зомби' и как это влияет на систему? В этой статье мы ясно объясним, что такое зомби-процесс (Zombie Process), как его обнаружить и решить проблему.
Что такое зомби-процесс (Zombie Process)? 🧟
Рассмотрим метафору жизненного цикла процесса для лучшего понимания.
-
Рождение (Fork): родительский процесс (Parent Process) создает дочерний процесс (Child Process) (
fork()). -
Исполнение (Exec): дочерний процесс выполняет свою задачу.
-
Завершение (Exit): дочерний процесс завершает выполнение и выходит (
exit()). -
Сбор (Wait): когда дочерний процесс завершен, операционная система (ядро) оставляет информацию о процессе, такую как PID и статус завершения, в таблице процессов. Затем отправляется сигнал
SIGCHLD(дочерний процесс завершен) родительскому процессу. -
Родительский процесс, получив этот сигнал, должен вызвать системный вызов
wait()для "сбора" информации о состоянии завершения дочернего процесса. Как только эта информация будет собрана, ядро окончательно удалит запись о дочернем процессе из таблицы процессов.
Зомби-процесс - это процесс, "застрявший" между 4-м и 5-м состоянием. То есть, дочерний процесс завершил выполнение, но родительский процесс еще не вызвал wait() для сбора его состояния.
Как следует из названия, этот процесс находится в мёртвом состоянии (не выполняется). Поэтому он не потребляет системные ресурсы, такие как CPU или память.
Почему зомби-процесс является проблемой?
Сами по себе зомби-процессы почти не используют ресурсы системы, но занимают один слот в таблице процессов (PID).
Если из-за ошибок родительского процесса зомби-процессы продолжают накапливаться и не удаляются, это может привести к исчерпанию максимального количества доступных PID в системе. В этом случае система больше не сможет создавать новые процессы, что может привести к серьезным сбоям. Наличие 1-2 зомби в top не является чем-то необычным, но если это число продолжает расти, необходимо принять меры.
Как проверить и идентифицировать зомби-процессы
Команда top показывает только _количество_ зомби-процессов. Чтобы узнать, какой процесс находится в состоянии зомби и кто его родитель, необходимо использовать команду ps.
Самый простейший способ — это найти процессы в состоянии 'Z' в колонке STAT команды ps.
# Отображение всех процессов с фильтром для состояния 'Z' (зомби)
ps -elf | grep ' Z '
# Или использовать опцию 'aux' (8-й столбец ($8) — состояние (STAT))
ps aux | awk '$8=="Z"'
Пример вывода :
# ps -elf | grep ' Z '
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
0 Z user 5021 5000 0 80 0 - 0 exit 15:30 ? 00:00:00 [defunct]
В данном примере важная информация включает:
-
S (Состояние):
Z(означает, что процесс в состоянии зомби) -
PID:
5021(это PID зомби-процесса) -
PPID:
5000(это PID родительского процесса, который не собрал зомби) -
CMD:
[defunct](имя, указывающее на то, что процесс завершился, но не был собран)
Способы решения проблемы зомби-процессов
Самое важное, что нужно знать: зомби-процессы нельзя убить с помощью команды kill.
kill -9 5021(PID зомби из примера выше)
Эта команда не сработает. Зомби уже в "мертвом" состоянии, и не существует субъекта, способного обработать сигнал kill.
Единственный способ решения проблемы зомби-процессов заключается в том, чтобы родительский процесс вызвал wait().
Шаг 1: Отправка сигнала родительскому процессу (рекомендуется)
Первое, что следует попробовать, — это вручную отправить сигнал SIGCHLD родительскому процессу (PPID) для проверки состояния дочернего процесса.
# Отправка сигнала SIGCHLD родительскому PID (5000) из примера выше
kill -s SIGCHLD 5000
Это указывает родительскому процессу: "Один из твоих дочерних процессов завершился, проверь это!". Если родитель правильно запрограммирован, он должен принять этот сигнал и собрать зомби.
Шаг 2: Принудительное завершение родительского процесса (последнее средство)
Если Шаг 1 не сработал, это может означать, что родительский процесс (PPID 5000) сам завис, или в его логике вызова wait() есть серьезная ошибка.
В этом случае принудительное завершение родительского процесса является единственным решением.
# Завершение родительского процесса (PPID 5000)
kill 5000
# Если всё еще не завершается, принудительное завершение
kill -9 5000
Почему завершение родителя решает проблему?
В Linux, когда родительский процесс завершается, дочерние процессы (сироты) автоматически "усыновляются" процессом init (PID 1) или systemd. Процесс init регулярно проверяет состояние своих дочерних процессов и оперативно собирает завершенные дочерние процессы (включая зомби).
Таким образом, когда проблемный родитель (PPID 5000) завершается, зомби (PID 5021) становится новым дочерним процессом init, и init немедленно очищает зомби.
⚠️ Внимание: Прежде чем завершить родительский процесс, обязательно проверьте, является ли этот процесс важной службой для системы (например, БД, веб-сервер и т. д.) с помощью команды
ps -p 5000(родительский PID). Принудительное завершение важной службы может привести к более серьезным сбоям.
Резюме
-
Зомби-процесс — это остаток в таблице процессов, который завершился, но родитель не собрал информацию о его завершении.
-
Он не потребляет ресурсы, но занимает PID, и если их слишком много, это может вызвать сбой системы.
-
Вы можете найти зомби (PID) и его родителя (PPID) с помощью команды
ps -elf | grep ' Z '. -
Решение направлено на родительский процесс (PPID), а не на зомби.
-
kill -s SIGCHLD <родительPID>(рекомендуется) -
kill <родительPID>(последнее средство)
-
Комментариев нет.