有没有办法识别哪个进程变成了僵尸进程

有没有办法识别哪个进程变成了僵尸进程

其中一台 ubuntu 服务器有 82 个僵尸进程。所有进程都将“[sh] defunct”显示为进程命令。有没有办法找出哪个进程正在变成僵尸进程?

我尝试检查/proc/PID/目录以获取有关僵尸进程的一些线索,但所有文件都是空的。如何找到谁让这个进程成为僵尸进程...还有其他方法可以查到吗?

更新/解决:使问题更清晰,并按照 andcoz 的建议回答了我自己的问题。

答案1

Linux 内核的审计子系统对于找出哪些进程正在变成僵尸进程非常有用。我刚刚遇到了以下情况:

server ~ # ps -ef --forest
[...]
root     16385     1  0 17:04 ?        00:00:00 /usr/sbin/apache2 -k start
root     16388 16385  0 17:04 ?        00:00:00  \_ /usr/bin/perl -T -CSDAL /usr/lib/iserv/apache_user
root     16389 16385  0 17:04 ?        00:00:00  \_ /usr/bin/perl -T -CSDAL /usr/lib/iserv/apache_user
www-data 16415 16385  0 17:04 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 18254 16415  0 17:23 ?        00:00:00  |   \_ [sh] <defunct>
www-data 18347 16415  0 17:23 ?        00:00:00  |   \_ [sh] <defunct>
www-data 22966 16415  0 18:18 ?        00:00:00  |   \_ [sh] <defunct>
www-data 16583 16385  0 17:05 ?        00:00:01  \_ /usr/sbin/apache2 -k start
www-data 18306 16583  0 17:23 ?        00:00:00  |   \_ [sh] <defunct>
www-data 18344 16583  0 17:23 ?        00:00:00  |   \_ [sh] <defunct>
www-data 17561 16385  0 17:12 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 22983 17561  0 18:18 ?        00:00:00  |   \_ [sh] <defunct>
www-data 18318 16385  0 17:23 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 19725 16385  0 17:43 ?        00:00:01  \_ /usr/sbin/apache2 -k start
www-data 22638 16385  0 18:13 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 22659 16385  0 18:14 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 25102 16385  0 18:41 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 25175 16385  0 18:42 ?        00:00:00  \_ /usr/sbin/apache2 -k start
www-data 25272 16385  0 18:44 ?        00:00:00  \_ /usr/sbin/apache2 -k start

这些僵尸进程的原因很可能是 PHP 脚本,但由于这些 Apache 子进程正在处理大量 HTTP 请求和大量不同的 PHP 脚本,因此很难找出哪个进程负责。 Linux 也已经释放了这些僵尸进程的重要信息,因此我们甚至不必/proc/<pid>/cmdline弄清楚可能正在运行哪个脚本或-c命令:/bin/sh

server ~ # cat /proc/18254/cmdline 
server ~ # 

为了弄清楚这一点,我安装了auditdhttps://linux-audit.com/configuring-and-auditing-linux-systems-with-audit-daemon/

我设置了以下审核规则:

auditctl -a always,exit -F arch=b32 -S execve -F path=/bin/dash
auditctl -a always,exit -F arch=b64 -S execve -F path=/bin/dash

这些规则审核/bin/dash二进制文件的所有进程创建。/bin/sh在这里不起作用,因为它是一个符号链接,并且审核显然只能看到目标文件名:

server ~ # ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Nov  8  2014 /bin/sh -> dash*

一个简单的测试现在应该会生成审核日志/var/log/audit/audit.log(我冒昧地添加了很多换行符以提高可读性):

server ~ # sh -c 'echo test'
test

server ~ # tail -f /var/log/audit/audit.log
[...]
type=SYSCALL msg=audit(1488219335.976:43871): arch=40000003 syscall=11 \
  success=yes exit=0 a0=ffdca3ec a1=f7760e58 a2=ffdd399c a3=ffdca068 items=2 \
  ppid=27771 pid=27800 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 \
  fsgid=0 tty=pts7 ses=7532 comm="sh" exe="/bin/dash" key=(null)
type=EXECVE msg=audit(1488219335.976:43871): argc=3 a0="sh" a1="-c" \
  a2=6563686F2074657374
type=CWD msg=audit(1488219335.976:43871):  \
  cwd="/var/lib/iserv/remote-support/iserv-martin.von.wittich"
type=PATH msg=audit(1488219335.976:43871): item=0 name="/bin/sh" inode=10403900 \
  dev=08:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL
type=PATH msg=audit(1488219335.976:43871): item=1 name=(null) inode=5345368 \
  dev=08:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL
type=PROCTITLE msg=audit(1488219335.976:43871): \
  proctitle=7368002D63006563686F2074657374

许多信息都经过编码,但ausearch可以使用以下命令进行翻译-i

server ~ # ausearch -i -x /bin/dash | tail                                      
[...]
----
type=PROCTITLE msg=audit(27.02.2017 19:15:35.976:43871) : proctitle=sh 
type=PATH msg=audit(27.02.2017 19:15:35.976:43871) : item=1 name=(null) \
  inode=5345368 dev=08:01 mode=file,755 ouid=root ogid=root rdev=00:00 \
  nametype=NORMAL 
type=PATH msg=audit(27.02.2017 19:15:35.976:43871) : item=0 name=/bin/sh \
  inode=10403900 dev=08:01 mode=file,755 ouid=root ogid=root rdev=00:00 \
  nametype=NORMAL 
type=CWD msg=audit(27.02.2017 19:15:35.976:43871) :  \
  cwd=/var/lib/iserv/remote-support/iserv-martin.von.wittich 
type=EXECVE msg=audit(27.02.2017 19:15:35.976:43871) : argc=3 a0=sh a1=-c \
  a2=echo test 
type=SYSCALL msg=audit(27.02.2017 19:15:35.976:43871) : arch=i386 \
  syscall=execve success=yes exit=0 a0=0xffdca3ec a1=0xf7760e58 a2=0xffdd399c \
  a3=0xffdca068 items=2 ppid=27771 pid=27800 auid=root uid=root gid=root \
  euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts7 \
  ses=7532 comm=sh exe=/bin/dash key=(null) 
----

如果您不想将ausearch过滤限制为/bin/dash,也可以使用ausearch -i -m ALL翻译完整的日志。ausearch -i -p <PID of a zombie process>在这种情况下,另一个好的过滤器是ausearch -i -p 27800

只需保留这些规则,直到出现新的僵尸进程,然后搜索僵尸 PID 的进程创建:

ausearch -i -p <PID>

这对于识别僵尸进程的根本原因应该非常有帮助。就我而言,它是一个 PHP 脚本,用于proc_open生成 Perl 脚本,而无需使用proc_close.

答案2

当然可以。有很多方法可以做到这一点,最常见的可能是:

ps aux

您可以添加一个基本的| grep -w Z僵尸,然后您将得到一个简短的僵尸列表。如果您只想要僵尸进程及其 pid 的列表,您可以按照这一页:

ps aux | awk '{ print $8 " " $2 }' | grep -w Z

查看这个问题有关流程信息的更多详细信息。

答案3

简短的回答是你不在乎。僵尸进程已死亡。对于进程表中的该条目,它所消耗的只是一小部分内核内存。

由于进程剩下的只是进程表条目,因此您几乎没有什么可继续的。僵尸进程是指其父进程尚未回收的死亡进程;查看进程的 PPID 以了解其父进程是谁。

答案4

ps auxf | grep --color -5 ' Z '

显示进程层次结构,包括僵尸及其父级识别僵尸脚本名称很困难,因为只有您看到“sh defunct”

相关内容