如何找到僵尸进程?


100
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:~$ 

如何找到僵尸进程?


为什么不打开系统监视器并搜索僵尸进程?
dlin 2012年

8
如何在无头No-X服务器上执行此操作?
SabreWolfy

2
令人惊讶的是,以下没有答案实际上表明,基于以上输出,系统中没有僵尸进程。如果确实存在一个,则该ps auxwww | grep 'Z'命令应该已显示处于Z状态的进程。“系统信息”的说法=> There is 1 zombie process.似乎是一个错误。要么是这样,要么是问题中缺少信息。
arielf

Answers:


126

要杀死一个僵尸(进程),您必须杀死它的父进程(就像真正的僵尸一样!),但是问题是如何找到它。

找到僵尸(问题回答了这一部分):

a@SERVER:~$ ps aux | grep 'Z'

您得到的是僵尸以及其中带有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的其他资源:


1
您在答案中显示的结果是grep命令本身,而不是僵尸进程。这和巴勃罗在回答中的误解是一样的。下面的Rinzwind答案实际上确实是在寻找僵尸进程并将其列出。另一个选择可能是grep表示“已停用”
FvD

pstree -H your_desired_pid -p
Greg M. Krsak 2014年

感谢Greg参与讨论,但请记住,这是一个帮助网站,仅粘贴命令而不说明任何内容对大多数来这里寻求帮助的人没有帮助。
Duncanmoo 2014年

1
这是一个很好的答案!今天仍然有效!我能够找到我的僵尸进程并杀死其父进程,而没有任何问题。谢谢!
Terrance

1
如果您没有安装pstree,ps wauxf则执行相同的操作
JDS

35

即使这个问题很老,我还是认为每个人都应该得到一个更可靠的答案:

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列表。

您现在可以使用简单的Shell循环在此列表上进行操作

for pid in $(ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }') ; do
    echo "$pid" # do something interesting here
done

ps 是一个功能强大的工具,您不需要做任何复杂的事情就可以获取过程信息。

(这里表示不同过程状态-https: //unix.stackexchange.com/a/18477/121634


2
awk还是功能强大的工具,它不仅可以拆分文本,还可以匹配文本。+1 ...其他人grep在不必要和不精确的地方使用了。
0xC0000022L 2014年

所以现在我有了僵尸进程列表。我该如何杀死他们?
chovy

@chovy:这将取决于,但通常涉及杀死或发信号给父母。这里有其他答案。在上面显示的循环中,您可以找到这样的父pid:ps -p "$pid" -opid=,ppid=
Sorpigal

如果我父母将不杀死它的所有子进程?我只想杀死一个僵尸进程。我知道了。
chovy

1
我确实建议添加ppid=到选项列表中,因此无需使用单独的命令来获取ppid。
鼎陈义

3

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;

但是要小心:这也杀死了程序。


仍然不返回任何内容。我认为我的方式也没错。
巴勃罗(Pablo)2012年

第二个示例令人难以置信,前一个示例不必要冗长(请尝试ps axo pid=,stat= | awk '$2~/Z/ {print $1}')。
Sorpigal

3

少即是多:

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层次结构中遵循该树/林;这就是我建议采用“少即是多”的方法的建议。


0

我建议您使用以下命令:

ps aux | awk '"[Zz]" ~ $8 { printf("%s, PID = %d\n", $8, $2); }'

使用aux和改写(munging)串出它是不必要的不可靠时,你可以使用-o,并要求你想要什么。使用ps ax -o pid=,stat= | awk '$2 ~ "[Zz]" { printf("%s, PID = %d\n", $2, $1); }'代替。
Sorpigal

-1

要列出进程僵尸,请尝试以下命令:

ps j | awk '$7 ~ "Z"'

您可能需要$7根据操作系统进行更改。

这还将返回其父进程ID(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)

为此,诉诸于从j格式中剥离一列是不必要的复杂。使用-o来选择你想要的东西来代替。
Sorpigal

2
ps j不会打印系统中的所有进程。它仅列出当前的用户进程(采用BSD作业样式),因此可能会丢失僵尸进程。
arielf
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.