우분투 서버 중 하나에는 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 ~ #
이를 파악하기 위해 다음을 설치했습니다 auditd
.https://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>
이는 좀비 프로세스의 근본 원인을 식별하는 데 매우 도움이 됩니다. 제 경우에는 proc_open
.NET Framework를 사용하지 않고 Perl 스크립트를 생성하는 것이 PHP 스크립트였습니다 proc_close
.
답변2
답변3
짧은 대답은 당신이 상관하지 않는다는 것입니다. 좀비 프로세스가 종료되었습니다. 프로세스 테이블에 있는 이 항목의 경우 커널 메모리의 작은 부분만 소비합니다.
프로세스에서 남은 것은 프로세스 테이블 항목뿐이므로 더 이상 진행할 작업이 거의 없습니다. 좀비 프로세스는 부모가 아직 재활용되지 않은 죽은 프로세스입니다. 프로세스의 PPID를 확인하여 부모가 누구인지 알아보세요.
답변4
ps auxf | grep --color -5 ' Z '
좀비와 그 부모를 포함한 프로세스 계층 표시 좀비 스크립트 이름을 식별하는 것은 "sh defunct"만 볼 수 있기 때문에 어렵습니다.