为什么进程/程序变成僵尸?


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

发生故障时会进行故障排除。僵尸没有麻烦。
吉尔斯(Gillles)“所以-别再邪恶了”

@吉尔斯,你是对的,但我需要照顾并找出预防措施吗?你认为呢 ?
Rahul Patil

他们没有麻烦,所以不,您不需要关心。
吉尔(Gilles)“所以,别再邪恶了”

Answers:


21

在此处输入图片说明

就像实际的僵尸一样,僵尸进程无法杀死,因为它已经死了。

怎么发生的

在Linux / Unix中,当进程死亡/结束时,该进程中的所有信息将从系统内存中删除,只有进程描述符保留。进程进入状态Z(僵尸)。他的父进程从内核获取信号:SIGCHLD,这意味着他的一个子进程退出,被中断或在被中断后恢复(在我们的情况下,它只是退出)。

现在,父进程需要执行wait()syscall才能从其子进程中读取退出状态和其他信息。然后将描述符从内存中删除,该过程不再是僵尸。

如果父进程从未调用过wait()syscall,则僵尸进程描述符将保留在内存中并吞噬大脑。通常您不会看到僵尸进程,因为上述过程花费的时间更少。

死者的黎明

每个进程描述符都需要非常少量的内存,因此一些僵尸并不是很危险(就像在现实生活中一样)。一个问题是每个僵尸进程都保留其进程ID,而Linux / Unix操作系统的pid数量有限。如果编程不当的软件生成了很多僵尸进程,则可能由于不再有可用的进程ID而无法启动进程。

因此,如果他们成群结队,那就非常危险(就像在许多电影中都很好地展示了)

我们如何捍卫自己免受僵尸大军的袭击?

头部射击会起作用,但是我不知道该命令(SIGKILL无法起作用,因为该过程已经死了)。

好了,您可以通过kill将SIGCHLD发送给父进程,但是当它忽略此信号时,该怎么办?您唯一的选择是杀死父进程,并且初始化进程“采用”僵尸。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系统调用做出反应,不应强制使用启示录。


1
什么,没有板球拍和LP?
Alexios

-3

如果父线程在其子线程之前被杀死,则所有子线程将成为僵尸进程。


7
不正确,它们将重新存在。僵尸进程没有调用waitpid。
克里斯·唐纳

也许他在谈论父母和孩子的过程。当其父进程“死亡”时,子进程将成为“孤儿”。
巴伦2013年
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.