왜 프로세스 / 프로그램이 좀비가됩니까?


13

스크립트가 명령 줄에서 제대로 실행되면 왜 cron을 통해 실행 한 후에 동일한 스크립트가 좀비 상태가되고 어떻게 동일한 문제를 해결합니까?

다음은 실제 예입니다.

[root@abc ~]# ps ax | grep Z
23880 ?        Zs     0:00 [checkloadadv.sh] <defunct>
23926 pts/0    S+     0:00 grep Z
[root@abc ~]# strace -p 23880
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted
[root@abc ~]# pstree | grep  checkload
init-+-crond---crond-+-checkloadadv.sh
[root@abc ~]# bash /usr/bin/checkloadadv.sh
System Load is OK : 0.05

문제가 발생하면 문제 해결이 이루어집니다. 좀비는 문제가되지 않습니다.
Gilles 'SO- 악의를 멈춰라'

@Gilles, 당신 말이 맞지만, 그들을 돌봐주고 예방해야합니까? 당신은 어떻게 생각하세요?
Rahul Patil

그들은 문제가되지 않으므로 걱정할 필요가 없습니다.
Gilles 'SO- 악의를 그만두십시오

답변:


21

여기에 이미지 설명을 입력하십시오

실제 좀비처럼 좀비 프로세스는 이미 죽었 기 때문에 죽일 수 없습니다.

어떻게 일어나는가

Linux / Unix에서 프로세스가 종료 / 종료되면 프로세스의 모든 정보가 시스템 메모리에서 제거되고 프로세스 디스크립터 만 유지됩니다. 프로세스는 상태 Z (좀비)에 도달합니다. 그의 부모 프로세스는 커널로부터 신호를받습니다 : SIGCHLD즉, 그의 자식 프로세스 중 하나가 종료 된 후 중단되거나 재개 됨 (이 경우에는 단순히 종료 됨)을 의미합니다.

상위 프로세스는 이제 wait()자신의 하위 프로세스에서 종료 상태 및 기타 정보를 읽으려면 syscall 을 실행해야합니다 . 그런 다음 설명자가 메모리에서 제거되고 프로세스는 더 이상 좀비가 아닙니다.

부모 프로세스가 wait()syscall을 호출하지 않으면 좀비 프로세스 디스크립터는 메모리에 남아 뇌를 먹습니다. 일반적으로 위의 절차는 시간이 덜 걸리기 때문에 좀비 프로세스가 표시되지 않습니다.

죽음의 새벽

각 프로세스 디스크립터는 매우 적은 양의 메모리를 필요로하므로 일부 좀비는 실생활처럼 위험하지 않습니다. 하나의 문제는 각 좀비 프로세스가 자신의 프로세스 ID를 유지하고 Linux / Unix 운영 체제에는 제한된 수의 pid가 있다는 것입니다. 잘못 프로그래밍 된 소프트웨어가 많은 좀비 프로세스를 생성하는 경우 더 이상 사용할 수있는 프로세스 ID가 없기 때문에 프로세스를 더 이상 시작할 수 없습니다.

그래서 그들이 큰 그룹에 있다면 그들은 매우 위험합니다 (많은 영화 에서처럼 잘 보여집니다)

우리는 어떻게 좀비 무리로부터 자신을 방어 할 수 있습니까?

헤드 샷은 작동하지만 그 명령을 알 수 없습니다 (프로세스가 이미 종료되어 SIGKILL이 작동하지 않습니다).

글쎄, 당신은 kill을 통해 SIGCHLD를 부모 프로세스로 보낼 수 있지만,이 신호를 무시하면 어떻게됩니까? 유일한 방법은 부모 프로세스를 종료하고 init 프로세스가 좀비를 "채택"하는 것입니다. Init은 주기적으로 wait()syscall을 호출하여 좀비 자녀를 정리합니다.

당신의 경우

귀하의 경우 SIGCHLD를 crond 프로세스로 보내야합니다.

root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit

그런 다음 다른 터미널에서 :

root@host:~$ kill -17 $(pgrep cron)

출력은 다음과 같습니다.

restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fff51be39dc, WNOHANG, NULL) = -1 ECHILD (No child processes) <-- Here it happens
rt_sigreturn(0xffffffffffffffff)        = -1 EINTR (Interrupted system call)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=1892, ...}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x403170, [CHLD], SA_RESTORER|SA_RESTART, 0x7fd6a7e9d4a0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({42, 0}, ^C <unfinished ...>
Process 1180 detached

wait4()syscall이 -1 ECHILD를 반환 하는 것을 볼 수 있습니다. 이는 자식 프로세스가 없음을 의미합니다. cron은 SIGCHLD syscall에 반응하며 종말을 강요해서는 안됩니다.


1
귀뚜라미 박쥐와 LP는 없습니까?
Alexios

-3

부모 스레드가 자식 스레드보다 먼저 종료되면 모든 자식 스레드가 좀비 프로세스가됩니다.


7
사실이 아니라, 그들은 단지 양육 될 것입니다. 좀비 프로세스에는 waitpid가 호출되지 않았습니다.
Chris Down

아마도 그는 부모와 자식 과정에 대해 이야기했을 것입니다. 자식 프로세스는 부모 프로세스가 "고아"가 될 때 "고아"가됩니다.
Barun
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.