Rah*_*til 15 process zombie-process
如果脚本从命令行运行良好,那么为什么相同的脚本在通过 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
Run Code Online (Sandbox Code Playgroud)
cha*_*aos 25
就像真正的僵尸一样,僵尸进程不能被杀死,因为它已经死了。
当在 Linux/Unix 中一个进程死亡/结束时,该进程的所有信息都从系统内存中删除,只有进程描述符保留。进程进入状态 Z(僵尸)。他的父进程从内核得到一个信号:SIGCHLD
,这意味着他的一个子进程退出,被中断或被中断后恢复(在我们的例子中它只是退出)。
父进程现在需要执行wait()
系统调用以从其子进程读取退出状态和其他信息。然后描述符从内存中移除,进程不再是僵尸进程。
如果父进程从不调用wait()
系统调用,僵尸进程描述符就会留在内存中并吃掉大脑。通常您不会看到僵尸进程,因为上述过程花费的时间更少。
每个进程描述符都需要非常少量的内存,所以一些僵尸并不是很危险(就像在现实生活中一样)。一个问题是每个僵尸进程都保留自己的进程 ID,而 Linux/Unix 操作系统的 pid 数量是有限的。如果一个不正确编程的软件产生了很多僵尸进程,可能会发生进程不能再启动的情况,因为没有更多的进程 id 可用。
所以,如果他们成群结队,他们是非常危险的(就像在许多电影中表现得很好)
头部中弹会起作用,但我不知道该命令(SIGKILL 不起作用,因为该进程已经死了)。
好吧,您可以通过 kill 将 SIGCHLD 发送到父进程,但是当它忽略此信号时,该怎么办?您唯一的选择是杀死父进程并且 init 进程“采用”僵尸进程。Init 定期wait()
调用系统调用来清理他的僵尸孩子。
在您的情况下,您必须将 SIGCHLD 发送到 crond 进程:
root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit
Run Code Online (Sandbox Code Playgroud)
然后从另一个终端:
root@host:~$ kill -17 $(pgrep cron)
Run Code Online (Sandbox Code Playgroud)
输出是:
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
Run Code Online (Sandbox Code Playgroud)
您会看到wait4()
系统调用返回 -1 ECHILD,这意味着那里没有子进程。所以结论是:cron 对 SIGCHLD 系统调用做出反应,不应该强迫天启。
归档时间: |
|
查看次数: |
11574 次 |
最近记录: |