Как найти зомби-процесс?
System information as of Fri Mar 9 19:40:01 KST 2012
System load: 0.59 Processes: 167
Usage of /home: 23.0% of 11.00GB Users logged in: 1
Swap usage: 0% IP address for eth1: 192.168.0.1
=> There is 1 zombie process.
Graph this data and manage this system at https://landscape.canonical.com/
10 packages can be updated.
4 updates are security updates.
Last login: Fri Mar 9 10:23:48 2012
a@SERVER:~$ ps auxwww | grep 'Z'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
usera 13572 0.0 0.0 7628 992 pts/2 S+ 19:40 0:00 grep --color=auto Z
a@SERVER:~$
Как найти этот процесс зомби?
9 ответов
Чтобы убить зомби (процесс), вы должны убить его родительский процесс (как настоящие зомби!), Но вопрос был в том, как его найти.
Найди зомби (на вопрос ответила эта часть):
a@SERVER:~$ ps aux | grep 'Z'
То, что вы получите, это Zombies и все остальное с Z в нем, так что вы также получите grep:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
usera 13572 0.0 0.0 7628 992 pts/2 S+ 19:40 0:00 grep --color=auto Z
usera 93572 0.0 0.0 0 0 ?? Z 19:40 0:00 something
Найдите родителя зомби:
a@SERVER:~$ pstree -p -s 93572
Дам тебе:
init(1)---cnid_metad(1311)---cnid_dbd(5145)
В этом случае вы не хотите убивать этот родительский процесс, и вы должны быть вполне довольны одним зомби, но уничтожение непосредственного родительского процесса 5145 должно от него избавиться.
Дополнительные ресурсы по Askubuntu:
Хотя этот вопрос старый, я думал, что все заслуживают более надежного ответа:
ps axo pid=,stat=
Это создаст два столбца, разделенных пробелами, первый из которых - PID, а второй - его состояние.
Я не думаю, что даже GNU ps
предоставляет возможность фильтрации по состоянию напрямую, но вы можете надежно сделать это с awk
ps axo pid=,stat= | awk '$2~/^Z/ { print }'
Теперь у вас есть список PID, которые являются зомби. Поскольку вы знаете состояние, его больше не нужно отображать, чтобы его можно было отфильтровать.
ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'
Предоставление списка разделенных новой строкой PID зомби.
Теперь вы можете работать с этим списком с помощью простого цикла оболочки
for pid in $(ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }') ; do
echo "$pid" # do something interesting here
done
ps
это мощный инструмент, и вам не нужно делать ничего сложного, чтобы извлечь из него информацию о процессе.
Меньше значит больше, хотя:
ps afuwwx | less +u -p'^(\S+\s+){7}Z.*'
Это как, дать мне лес (дерево) всех пользовательских процессов в ориентированном на пользователя формате с неограниченной шириной для любого tty и показать его мне на половине экрана выше, где это соответствует случаю, когда 8-й столбец содержит Z, и почему бы не выделить всю строку.
Пользовательский формат, кажется, означает:USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMAND
поэтому статус зомби будет отображаться в 8-м столбце.
Вы можете бросить в N
перед p
если вы хотите, чтобы номера строк, и J
если вы хотите звездочку на матче. К сожалению, если вы используете G
не выделять строку, которую звездочка не покажет, хотя J
создает пространство для этого.
В итоге вы получаете что-то похожее на:
…
root 2919 0.0 0.0 61432 5852 ? Ss Jan24 0:00 /usr/sbin/sshd -D
root 12984 0.0 0.1 154796 15708 ? Ss 20:20 0:00 \_ sshd: lamblin [priv]
lamblin 13084 0.0 0.0 154796 9764 ? S 20:20 0:00 \_ sshd: lamblin@pts/0
* lamblin 13086 0.0 0.0 13080 5056 pts/0 Z 20:20 0:00 \_ -bash <defunct>
lamblin 13085 0.0 0.0 13080 5056 pts/0 Ss 20:20 0:00 \_ -bash
root 13159 0.0 0.0 111740 6276 pts/0 S 20:20 0:00 \_ su - nilbmal
nilbmal 13161 0.2 0.0 13156 5004 pts/0 S 20:20 0:00 \_ -su
nilbmal 13271 0.0 0.0 28152 3332 pts/0 R+ 20:20 0:00 \_ ps afuwwx
nilbmal 13275 0.0 0.0 8404 848 pts/0 S+ 20:20 0:00 \_ less +u -Jp^(\S+\s+){7}Z.*
…
Вы можете выполнить это с помощью (и он обнаружит, нравится ли вашему терминалу -U Unicode или -A Ascii):
pstree -psS <PID LIST>
ИЛИ просто, вы знаете, используйте стрелку вверх в less
следовать этому дереву / лесу через иерархию; это то, что я рекомендовал с подходом "Меньше значит больше".
Обычно я нахожу их на своем сервере с помощью
ps aux | grep 'defunct'
ps aux | awk '{ print $8 " " $2 }' | grep -w Z
От: http://www.cyberciti.biz/tips/killing-zombie-process.html
Из комментариев улучшенный:
for p in $(ps jauxww | grep Z | grep -v PID | awk '{print $3}'); do
for every in $(ps auxw | grep $p | grep cron | awk '{print $2}'); do
kill -9 $every;
done;
done;
Осторожно, хотя: этот также убивает процесс.
Хотя ответы Дламбина и Сорпигала превосходны и прекрасно выполняют свою работу, я просто хотел задокументировать свои выводы о том, как использоватьawk
чтобы найти столбец STAT при переключении между форматами вывода вместо его жесткого кодирования:
ps au | awk '{
if (NR==1) {
for (i=1; i<=NF; i++) {
if ($i=="STAT")
stat=i
};
print
} else if ($stat~/^Z/)
print
}'
Здесь будут перечислены все процессы вps
«ориентированный на пользователя формат» и передать его в awk. В строке заголовка (NR = номер записи ==1) он пройдет все поля (вплоть до NF = количества полей) и сохранит номер поля, которому соответствует строка «STAT», в переменной stat, а затем продолжит печать строки. . Для всех остальных записей (строк) он проверит этот столбец на соответствие регулярному выражению, начинающемуся с заглавной буквы Z, и только затем распечатает строку.
Сокращенная версия:
ps au|awk '{if(NR==1){for(i=1;i<=NF;i++){if($i=="STAT")stat=i};print}else if($stat~/^Z/)print}'
Я предлагаю вам эту команду:
ps aux | awk '"[Zz]" ~ $8 { printf("%s, PID = %d\n", $8, $2); }'
Чтобы вывести список процессов зомби, попробуйте эту команду:
ps j | awk '$7 ~ "Z"'
Вам может понадобиться изменить $7
в зависимости от вашей операционной системы.
Это также вернет список их идентификаторов родительского процесса (PPID
).
Чтобы попытаться убить зомби (после проверки вышеуказанной команды), попробуйте:
kill -9 $(ps j | awk 'NR>1 && $7 ~ "Z" {print $2}')
Чтобы определить своих родителей, попробуйте с pstree
, лайк:
$ ps j | awk 'NR>1 && $7 ~ "T" {print $2}' | xargs -L1 pstree -sg
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2430)
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2431)
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2432)
почему мы не сообщаем «ps», какую информацию мы хотим получить? давайте попробуем:
read zSTAT zPPID zPID zSTAT zCMD <<< $(ps -xao stat,ppid,pid,cmd|awk '$1=="Z" {print $1" "$2" "$3" "$4}')
[[ ! -z ${zPPID} ]] && echo "Zombie found! PID: "${zPID}" ("${zCMD}"), Parent to kill: "${zPPID}
этот способ довольно быстрый и работает нормально. но осторожно! Система помечает множество процессов на короткое время как зомби, через несколько мс они пожинаются и исчезают ... поэтому обязательно подсчитывайте переменную и реагируйте только на зомби, которые не пожинаются после третьего обнаружения подряд. .. тогда я должен убить родительский процесс, потому что процессор нагревается, работая на максимальной частоте, потребляя много электроэнергии для родительского процесса, который больше не работает должным образом...
проверка того, пожат ли зомби или нет, может быть быстрее, если мы проверим только один параметр:
zombie=$(ps -xao pid|awk '$1=="'${zPID}'" {print $1}')
[[ ! -z ${zombie} ]] && sudo kill -KILL ${zPPID}