Избавиться от процессов-зомби
- имя
zombie-reaper- образ
python:3.12-slim- таймаут
- 30с
Задание
Избавиться от процессов-зомби
В контейнере крутится демон zombie-maker — он плодит дочерние процессы,
которые завершаются, но родитель их не wait()'ит. В итоге в таблице
процессов копятся зомби (Z в ps//proc/<pid>/stat). init: true в
docker-compose отключён (намеренно) — это и есть условие задачи.
Симптомы
$ ps -eo pid,ppid,stat,cmd | awk '$3 ~ /Z/'
123 122 Z [python3] <defunct>
125 122 Z [python3] <defunct>
...
Или через /proc:
$ for p in /proc/[0-9]*; do
s=$(awk '{print $3}' "$p/stat" 2>/dev/null)
[ "$s" = "Z" ] && echo "$p zombie"
done
Что нужно
Ни одного процесса в состоянии Z (zombie), чей командный путь или args
содержат python3 (маркер лабы — дочерние процессы демона).
Почему это hard
«Убить зомби» через kill -9 <pid> нельзя — зомби уже мёртв, ему нельзя
послать сигнал. Единственный способ убрать зомби — заставить родителя
сделать wait() (читать exit-статус), либо убить родителя (тогда зомби
репаются init'ом). В Docker без init: true PID 1 — это ваш процесс, и он
не всегда корректно репает детей. Решение зависит от архитектуры:
- Если можете — почините родителя (демона), чтобы он корректно
wait()'ил. - Если родителя трогать нельзя — перезапустите его или поставьте
tini
(легковесный init) как PID 1. - В реальном Docker: добавьте
init: trueв compose — но в этой лабе вы
внутри контейнера, поэтому тот же эффект даётexec tini -g -- <cmd>или
ручной reaper.
Подсказки
ps -eo pid,ppid,stat,cmd— найти PPID зомби (это и есть «виновный» родитель).kill <PPID>убивает родителя; ядро репает его детей (включая зомби).- Или:
apt-get install -y tini && exec tini -g -- zombie-maker— tini
становится PID 1 и репает всех отпрысков. - После решения демонстрация
zombie-makerдолжна продолжать работать, но
зомби не накапливать.
Подсказки
Hints: zombie-reaper
Ключевое понимание
Зомби — это уже мёртвый процесс: ядро сохранило для него exit-статус, но
родитель ещё не забрал его через wait()/waitpid(). Поэтому:
kill -9 <zombie-pid>не работает. Зомби нельзя «убить ещё раз».- Сигналы ему не доставляются — ему некуда.
Как избавиться
- Заставить родителя
wait()'ить. Это «правильный» фикс в реальном коде —
но родительzombie-makerв этой лабе намеренно багом, его код можно
править. - Убить родителя — тогда зомби становятся сиротами и репаются init'ом
(PID 1). В Docker безinit: truePID 1 — это sh, который сам по себе
reaper'ом не является, поэтому убивать родителя нужно осторожно. - Поставить reaper как PID 1.
tini(илиdumb-init) — мини-init,
единственная задача которого — репать зомби. В docker-compose это
init: true, но изнутри контейнера тот же эффект даёт
exec tini -g -- <cmd>.
Конкретные шаги в этой лабе
ps -eo pid,ppid,stat,cmd | grep -E ' Z '— увидеть зомби и их PPID.cat /proc/<zpid>/stat | awk '{print $1, $3, $4}'— pid, comm, state, ppid.- Убить
zombie-maker(PPID зомби):pkill -f zombie-maker— зомби репаются. - Чтобы демон не вернулся (его никто не перезапускает в этой лабе) —
достаточно простоpkill. - Альтернатива:
apt-get install -y tiniи запустить демона под tini:
setsid tini -g -- zombie-maker &.
Терминал
Закрывается при остановке сессии.
Последние попытки
- Загрузка…
Разовый запуск (smoke-тест)
Атомарный цикл up → check → down. Полезно для CI; без предварительной подготовки состояния проверка завершится с ошибкой.