在我的crontab:
* * * * * /tmp/launcher.sh /tmp/tester.sh
#!/bin/bash # the real script does a little argument processing here "$@"
#!/bin/bash sleep 27 & # the real script launches a compiled C program in the background
ps显示如下:
user 24257 24256 0 18:32 ? 00:00:00 [launcher.sh] <defunct> user 24259 1 0 18:32 ? 00:00:00 sleep 27
请注意,tester.sh不会出现 – 它在启动后台作业后退出.
为什么launcher.sh贴在周围,标记为< defunct>?它只是在cron启动时才会这样做 – 而不是当我自己运行时.
附加说明:launcher.sh是系统运行的常用脚本,不易修改.其他的东西(crontab,tester.sh,甚至我运行的程序,而不是睡眠)可以更容易地修改.
由于有人可能会等待这些进程在未来,内核不能完全摆脱它们,否则将无法执行等待系统调用,因为它不会有退出状态或其存在的证据.
当您从shell启动一个shell时,shell正在捕获SIGCHLD并进行各种等待操作,所以没有任何延迟.
但是,cron并没有处于等待状态,它正在睡觉,所以已故的孩子可能会坚持一段时间,直到cron醒来.
更新:回应评论…
嗯.我没有设法复制这个问题:
PPID PID PGID SESS COMMAND 1 3562 3562 3562 cron 3562 1629 3562 3562 \_ cron 1629 1636 1636 1636 \_ sh <defunct> 1 1639 1636 1636 sleep
所以,发生了什么事,我想:
cron fork和cron小孩启动shell
> shell(1636)启动sid和pgid 1636并开始睡眠
> shell出口,SIGCHLD发送到cron 3562
>信号被忽略或误操作
> shell转僵尸.注意,睡眠被重新设置为init,所以当睡眠退出init将得到信号并清理.我还在试图找出僵尸何时获得收获.可能没有活跃的孩子cron 1629可以退出,那时僵尸将被重新启动并获得收获.所以现在我们想知道cron应该处理的缺失的SIGCHLD.>并不一定是cron的错误.正如你可以在这里看到的,libdaemon installs a SIGCHLD handler在daemon_fork()期间,这可能会干扰中间的快速退出的信号传递1629Now,我甚至不知道我的Ubuntu系统上的vixie cron是否甚至使用libdaemon构建,但至少我有一个新的理论.