- Зомби процесът е прекратен дъщерен процес, който остава в таблицата с процеси, защото родителят му не е извикал wait().
- Те се откриват с команди като ps и top, където се появяват със Z статус или са обозначени като .
- Те не консумират процесорна мощност, но много зомбита могат да запълнят таблицата с процеси и да причинят сериозни проблеми.
- Правилното почистване включва принуждаване на родителския процес да събере състоянието на детето, използвайки сигнали като SIGHUP или SIGCHLD.
В света на GNU/Linux и други UNIX системи, говорейки за зомби процеси Няма нищо общо с телевизионни сериали или филми на ужасите, въпреки че името е доста подходящо. Отнася се до онези полумъртви, полуживи процеси, които се задържат в таблицата с процеси и ако се натрупат, могат да причинят доста главоболия на системния администратор.
Важно е да се разбере какво представляват те, как се създават и как... откриване на зомби процеси в Linux (и в macOSи най-вече как да ги премахнете, без да повредите нещо важно. По-долу ще намерите подробно обяснение, съчетаващо системна теория, практически примери с команди като ps o връх, няколко метода за прекратяване на тези мъртви процеси и дори малка C програма за генериране на тестов зомби.
Какво точно е зомби процес в Linux?
Зомби (или нефункциониращ) процес Това е дъщерен процес, който вече е завършил изпълнението си, но все още запазва запис в таблицата с процеси на системата. Този запис остава, за да може родителският процес да направи заявка към кода за изход на детето, използвайки извиквания като изчакайте() o изчакващ ID()Докато бащата не направи това четене, синът не изчезва напълно.
От метафорична гледна точка, синът е починал, но неговият „Душата“ все още е регистрирана в системата. Ето защо те се наричат зомбита или мъртви процеси: те вече не изпълняват код, не консумират процесорна или потребителска памет, но заемат малко място в таблицата с процеси. Ако има един или два, това не е проблем, но ако лошо програмирано приложение генерира много, можем да се сблъскаме с проблеми.
В Unix и Linux системите, когато даден процес приключи, ядрото освобождава ресурсите си (памет, файлови дескриптори и др.), но запазва този минимален запис със състоянието на изход. Ако родителят никога не извиква wait()Този запис не се изчиства и процесът остава маркиран като „зомби“. С други думи, почти винаги е проблем с програмирането или дизайна на софтуера, който действа като родителски процес.
Тези процеси са лесно разпознаваеми, защото в инструменти като ps се появяват със статуса Z (на зомби) или с етикета и на монитори като връх Има специфични броячи, които показват колко зомбита имаме активни в системата във всеки един момент.

Състояния на процесите в Linux
За да разберем ролята на зомбитата, е полезно да прегледаме състояния на процеса по-често срещани в Linux. Когато изброяваме процеси с ps o връхЗа обозначаване на състоянието се използва буква:
- Спящ (S): процеси, които спят, чакат своя ред за изпълнение или за настъпване на някакво събитие.
- Бягане (R): процеси, които се изпълняват на процесора или са готови за изпълнение.
- Чакане (D)блокирани процеси, чакащи завършването на входно/изходна операция (непрекъсваемо чакане).
- Спряно (Т): процеси, спрени например от сигнали като SIGSTOP или защото са в режим на отстраняване на грешки.
- Зомби (Z): процеси, които са завършили, но продължават да се показват в таблицата с процеси, чакайки родителят им да прочете състоянието им на изход.
Всеки ред от ps Показва процес с неговия PID, PPID (родителски PID), потребител, статус и други данни. Полето за статус може да се нарече S, STAT или подобно, според параметрите на ps. Процес със състояние Z Официално е зомби. В много случаи името на командата или процеса ще се показва като което ясно показва, че е починал.
Как да открием зомби процеси в Linux от терминала
Най-прекият начин за локализиране на зомби процеси е чрез използване на класически команди за наблюдение: ps y връхКомбинирайте ги с инструменти като Впиши, AWK o xargs Това позволява филтриране и подготовка на списъци с PID-ове със значителна точност.
Една от най-използваните команди за виждане на зомбита е:
ps -el | grep 'Z'
Параметър -Ел Това кара PS да показва разширен изход, където втората колона обикновено показва състоянието на процеса. В тази колона можем да намерим, наред с други неща:
- S: спи.
- Rбягане.
- Dчакане (непрекъснато чакане).
- T: спрян или gestopt (преустановен).
- Z: зомби (несъществуващ).
За по-подробен пример, на машина с проблемни процеси може да получим нещо подобно:
ps -el | grep 'Z'
FS UID PID PPID C PRI NI АДРЕС SZ WCHAN TTY ВРЕМЕ КОМАНДА
1 Z 0 1213 589 0 75 0 – 0 функция> ? 00:00:00 dovecot-auth
Тук виждаме, че процесът dovecot-auth Маркирано е със статус Z, така че е зомби. Вижте и колоната. PPIDзащото това е PID на родителския процес, за който ще говорим по-късно, за да почистим правилно зомбито.
Друг много често срещан начин за изброяване на зомбита е използването на комбинацията:
ps -A -ostat,ppid,pid,cmd | grep -e '^'
В този случай с -A Изброяваме всички процеси и опциите -o Това ни позволява да дефинираме точно колоните, които искаме: статус (stat), PPID, PID и командата. Филтърът grep -e '^' Запазва само редовете, чието състояние започва със Z oz, т.е. зомби процесите.
Друг, малко по-минималистичен вариант би бил:
ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'
В тази версия, ние искаме само PID и статус, без заглавки (с pid=,stat=), а след това с AWK Филтрираме редовете, чието поле за състояние започва със Z, като отпечатваме само PID-а на зомби процеса. Това е елегантен начин за генериране на списък със зомби PID-ове за по-късна употреба. убие или с други тръби.

Използване на top за локализиране на зомби процеси
Командата връх Това е много удобен интерактивен инструмент за наблюдение в реално време на случващото се в системата. В горната част на връх Показва се обобщение, показващо общия брой задачи и колко са във всяко състояние, включително колко зомбита По това време има активи.
За да го използвате, просто изпълнете:
връх
На първия или втория ред ще видите нещо подобно: Задачи: общо 150, 1 бягаща, 149 спяща, 0 спряла, 1 зомбитаТози брояч на зомбита вече ви показва дали има мъртви процеси, висящи от системата. Освен това, когато превъртате надолу списъка с процеси, в колоната S (щат), ще можете лесно да намерите тези, маркирани с Z.
Едно ограничение на `top` е, че въпреки че показва колко зомбита има, не винаги е толкова удобен, колкото `ps` за извличане само на тези процеси. Ето защо е много често срещано да се комбинират: първо проверявате с `top` дали има зомбита и след това използвате `ps`. ps с филтрите, които видяхме, за да ги идентифицираме подробно и да подготвим командите, които ще ги елиминират.
Някои статии предлагат и друга специфична команда за преглед на нефункциониращи процеси с повече информация:
ps axo stat,ppid,pid,comm | grep -w не е валиден
Тази команда се фокусира върху процеси, чиято команда е маркирана като несъществуващ; отново ще видите състоянието, родителския PID, дъщерния PID и свързаната с тях команда, което значително улеснява проследяването на проблема до родителския процес.

Какво се случва в ядрото при зомби процес
На вътрешно ниво на ядрото на Linux, всеки процес е представен от структура от данни, наречена структура task_structВ тази структура има полета, които показват състоянието на процеса, включително изходно_състояние, където се съхранява състоянието на изход, когато процесът приключи.
Когато даден процес приключи, ядрото го маркира със стойност, например ИЗХОД_ОТ_ЗОМБИ (дефинирано в заглавките на ядрото) в рамките на това поле изходно_състояниеТова означава, че процесът вече е завършил, но все още чака родителската програма да събере изходната информация. Стига родителската програма да не е изпълнена изчакайте()Ядрото не променя това състояние, нито премахва напълно записа от таблицата с процеси.
Интересният детайл е, че въпреки че зомбито не консумира значително количество процесор или работна памет, то го прави... заема слот в таблицата на процеситеИ тази таблица има краен размер. Ако дадено приложение създава дъщерни процеси в цикъл, които никога не се почистват (защото родителят не извиква wait()), може да се окажем със стотици или хиляди зомбита, изчерпвайки капацитета на таблицата и причинявайки повреди при създаването на нови процеси.
Как да прекратим зомби процесите в Linux
След като открием зомби процеси, трябва да помислим как ефективно да ги „убием“. Ето един ключов момент: Процесът на зомбиране вече е мъртъв.в смисъл, че не работи. Следователно, изпращането на сигнали като SIGKILL (kill -9) директно към зомбито е безполезно; няма код, който да обърне внимание на този сигнал.
Това, което наистина трябва да се направи, е да се получи родителският процес чете състоянието на изхода на дететоТова може да се постигне по няколко начина: чрез изпращане на подходящи сигнали до родителя, чрез принуждаване на родителя да прекрати процеса (така че init или systemd да приемат зомбито и да го почистят) или чрез използване на комбинации от команди, които автоматизират тази задача.
Първи вариант: изпратете SIGHUP до родителя
Много често срещано решение е да се намери PPID на зомби процеси и изпраща сигнал към родителя да изпълни wait() и да събере състоянията на своите деца. Типична команда е:
kill -HUP `ps -A -ostat,ppid,pid,cmd | grep -e '^' | awk '{print $2}'`
Ето какво се случва: първо, всички процеси се изброяват със статуса им, PPID, PID и команда; след това се филтрират тези, чийто статус започва със Z; и накрая, с awk '{print $ 2}' Втората колона е извлечена, която е PPID (идентификаторът на родителския процес). Този списък с родителски PID-ове се предава на убий -HUP, който изпраща сигнала ВДИХАНЕ на всеки един.
В много приложения този сигнал кара родителския процес да презареди конфигурацията си или да извърши почистване. В този контекст идеята е родителят да направи изчакайте() подходящо и отървете се от зомбитатаТова е доста агресивен, но практичен метод, особено когато има натрупани много зомбита и е известно, че те споделят един и същ родителски процес.
Втори вариант: използвайте SIGCHLD
Друг подход включва изпращането на сигнала SIGCHLD към проблемния родителски процес. Този сигнал казва на процеса, че едно от неговите деца е променило състоянието си (например, е прекратено). Обикновено, когато дъщерен процес приключи, ядрото изпраща SIGCHLD към родителя; ако родителят има конфигуриран обработчик на сигнали, той обикновено извиква изчакайте() в рамките на този манипулатор.
Ако откриете, че няколко зомбита имат един и същ PPID, можете да опитате:
убий -s SIGCHLD
Например:
убий -s SIGCHLD 2201
С това си ти спомняйки си бащата който има чакащи мъртви деца. Ако родителският процес е добре програмиран да реагира на SIGCHLD, той ще почисти своите зомбита, използвайки wait(). Този метод е по-малко рязък от прекратяването на родителя и, ако програмата е добре написана, е най-естественият начин за разрешаване на проблема.
Трети вариант: убиване на родителския процес
Ако родителският процес е блокиран, не реагира на сигнали като SIGHUP или SIGCHLD или очевидно е замръзнал, друга възможност е да го прекратите принудително. В този случай се използва класическият метод:
убий -9
Например:
kill -9 2201
Правейки това, ядрото прекратява родителския процес. В повечето съвременни системи, systemd или процесът първоначален Те осиновяват сираците (включително зомбитата) и са отговорни за извикването на wait() върху тях, по този начин почистете входа си в таблицата на процесите. Това не е най-елегантният начин, но понякога е единственият начин да се отървете от колекция от зомбита, произхождащи от дефектна програма.
Други разширени комбинации с ps, awk и kill
В допълнение към горните примери, има много шеги, които автоматизират търсенето на зомбита и изпращането на сигнали към техните родителски процеси. Някои представителни примери са:
ps axo state,pid | awk '$1==»2″ {print $2}' | xargs kill -s SIGKILL
Тази команда избира процеси въз основа на числовата стойност на техния статус; обаче се използва по-рядко, защото е по-трудно четима от работата с буквата Z. Други често срещани команди за справяне със зомбита са:
ps -xaw -o state,ppid | grep Z | grep -v PID | awk '{ print $2 }' | xargs kill -9
О, добре:
kill -9 `ps xawo state=,pid= | sed -n 's/Z //p''
или дори:
kill -9 `ps -xaw -o state -o ppid | grep Z | grep -v PID | awk '{print $2}'`
Във всички случаи идеята е подобна: локализират се процеси със състояние Z, извличат се техните PID или съответните PPID и се прилагат... убие със сигнала, който сметнем за подходящ (SIGHUP, SIGCHLD, SIGKILL и др.). Тези рецепти обаче трябва да се използват с известно внимание, защото убиване на важни родителски процеси Без да се замисляте, това може да доведе до прекъсване на услугите или до нестабилност на системата.
Практически пример: създаване на зомби процес с C
За да можете да провеждате тестове, без да повредите нищо, се използва класическа техника създаване на зомби процес по контролиран начин с малка програма на C. По този начин можем да видим точно как изглежда в ps, как е маркирано като и упражнете командите за премахването му.
Една много проста програма, която генерира зомби, може да бъде следната:
#include
#включва
#включва
intmain()
{
pid_t дете_pid;
child_pid = fork();
ако (child_pid > 0) {
сън (60);
}
още {
изход (0);
}
0 върне;
}
В този код, родителският процес прави вилица ()Синът веднага завършва с изход (0)докато бащата остава спи 60 секундиПрез това време синът е мъртъв, но бащата все още не се е обадил. изчакайте()така детето остава в състояние на зомби в таблицата на процесите.
За да компилирате тази програма, можете да използвате GCC както следва:
gcc -o zombie1 zombie.c
И за да го стартирате във фонов режим, просто:
./зомби1 &
Докато бащата още спи, можеш да екзекутираш ps -el | grep 'Z' или някоя от горните команди и ще видите вашия зомби процес в действие. След няколко секунди, когато родителският процес приключи и системата се почисти, зомбито ще изчезне.
Въздействие на зомби процесите и често срещани причини
Единичен, изолиран зомби процес, Обикновено не е причина за безпокойство.Не изразходва процесорна мощност, паметта, свързана с процеса, вече е освободена и прякото въздействие върху производителността е минимално. Проблемът възниква, когато се натрупат много „зомби“ процеси, обикновено защото софтуерът е лошо проектиран или има грешки в управлението на дъщерните си процеси.
Най-честите причини за зомбита са:
- Лошо програмиранеРодителският процес създава дъщерни процеси, но не имплементира правилно SIGCHLD управлението или не извиква wait() или waitpid(), за да събере състоянието на дъщерните процеси.
- грешки в конфигурациятаНякои услуги могат да създават дъщерни процеси в цикъл при определени конфигурации, които не са предвидени от разработчика, генерирайки каскада от зомбита.
- Родителският процес се срива или замръзваАко родителят се заби в I/O операция или в безкраен цикъл, това може да остави мъртвите деца непочистени.
Когато има много зомби процеси, таблицата с процеси може да се запълни с невалидни записикоето затруднява създаването на нови процеси и генерира симптоми като бавност, грешки при стартиране на приложения или странно поведение в критични услуги (например уеб сървъри като Apache, генериращи стотици нефункциониращи процеси).
Ето защо е важно да се консултирате с [понякога/от време на време] връх o ps Ако има зомбита, особено на производствени сървъри, е изключително важно да се коригира първопричината: актуализиране на проблемния софтуер, коригиране на кода, който управлява дъщерните процеси, или коригиране на конфигурации, които причиняват неконтролираното създаване на дъщерни процеси.
Графични алтернативи за потребители на настолни компютри
Ако не ви е удобно да използвате терминала или просто предпочитате визуално решение, много графични среди на Linux ви позволяват да използвате командния ред. Системен монитор (Системен монитор) или еквивалентни инструменти, които предлагат графичен изглед на процесите.
Общата процедура би била нещо подобно:
- Отворете приложението Системен монитор от менюто на работния плот.
- Отидете в раздела процеси, където са изброени всички активни процеси.
- Използвайте инструмента за търсене (обикновено икона на лупа), за да търсите термини като зомби или погледнете колоната за състояние, за да намерите процеси, маркирани като или З.
- Изберете проблемния процес, щракнете с десния бутон върху него и изберете опцията за „Убий“ или „Край на процеса“.
За да работи това правилно, е важно да се уверите, че мониторът показва всички системни процеси И не само тези на текущия потребител. Обикновено в настройките има квадратче за отметка или опция, която ви позволява да „Показвате процеси от всички потребители“ или нещо подобно.
Добри практики за предотвратяване на разпространението на зомбита
Освен триковете за убиване на зомбита, след като са се появили, си струва да приложите и някои добри практики да се сведе до минимум появата на тези процеси в производствените системи.
Сред най-важните препоръки са:
- Поддържайте системата и софтуера актуалниЧесто зомби процесите произлизат от грешки, които вече са били отстранени в по-късни версии на сървър или приложение.
- Преглед на планирането на дъщерните процесиАко разработвате софтуер, който използва fork(), уверете се, че обработвате SIGCHLD правилно и извиквате wait() или waitpid() за всяко дете, което прекратява изпълнението си.
- Следете периодичноВключването на команди като ps -el, ps axo stat,ppid,pid,comm или top в скриптове за наблюдение или инструменти за наблюдаемост помага за незабавното откриване на пикове на „зомби“ атаки.
- Разследвайте произхода, когато се появяват повтарящи се зомбитаАко те винаги са деца на определена услуга (например пощенски сървър или конкретен демон), може да се наложи да прегледате нейната конфигурация или версия.
Понякога дори са публикувани специфични сценарии (например, наречени zombie.shТези процеси автоматизират цялата тази логика: те локализират „зомби“ процеси, идентифицират техните родителски процеси, изпращат съответните сигнали и се опитват да почистят таблицата с процеси. Те са полезни като последна мярка, когато ръчните методи се провалят, но винаги е важно да знаете какво правят зад кулисите, за да избегнете изненади.
В крайна сметка, разбирането какво е зомби процес, как да го разглеждаме с ps y връхкак работят сигналите ВДИХАНЕ, SIGCHLD y SIGKILL относно родителските процеси и какви програмни модели водят до това състояние, ви позволява диагностицираме и решаваме с лекота практически всеки проблем, свързан с неработещи процеси в Linux, поддържайки вашите системи по-чисти, по-стабилни и с таблицата с процеси под контрол.
Страстен писател за света на байтовете и технологиите като цяло. Обичам да споделям знанията си чрез писане и това е, което ще направя в този блог, ще ви покажа всички най-интересни неща за джаджи, софтуер, хардуер, технологични тенденции и много други. Моята цел е да ви помогна да се ориентирате в дигиталния свят по лесен и забавен начин.