Joh*_*nck 14 bash cron background zombie-process defunct
我有一些进程显示<defunct>
在top
(和ps
)中.我从真实的脚本和程序中榨取了一些东西.
在我的crontab
:
* * * * * /tmp/launcher.sh /tmp/tester.sh
Run Code Online (Sandbox Code Playgroud)
的内容launcher.sh
(这是当然的标记为可执行):
#!/bin/bash
# the real script does a little argument processing here
"$@"
Run Code Online (Sandbox Code Playgroud)
的内容tester.sh
(这是当然的标记为可执行):
#!/bin/bash
sleep 27 & # the real script launches a compiled C program in the background
Run Code Online (Sandbox Code Playgroud)
ps
显示以下内容:
user 24257 24256 0 18:32 ? 00:00:00 [launcher.sh] <defunct>
user 24259 1 0 18:32 ? 00:00:00 sleep 27
Run Code Online (Sandbox Code Playgroud)
请注意,tester.sh
它不会出现 - 它在启动后台作业后退出.
为什么要launcher.sh
坚持,标记<defunct>
?它似乎只是在启动cron
时执行此操作 - 而不是在我自己运行它时.
附加说明:launcher.sh
是运行的系统中的常见脚本,不容易修改.其他的东西(crontab
,tester.sh
甚至是我运行的程序,而不是sleep
)可以更容易地修改.
Dig*_*oss 13
因为它们还没有成为wait(2)
系统调用的主题.
由于某人可能会在将来等待这些进程,因此内核无法完全摆脱它们,或者它无法执行wait
系统调用,因为它不再具有退出状态或其存在的证据.
当你从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
Run Code Online (Sandbox Code Playgroud)
那么,发生了什么事,我想:
daemon_fork()
此期间安装了一个SIGCHLD处理程序,这可能会干扰中间1629快速退出时的信号传递现在,我甚至不知道我的Ubuntu系统上的vixie cron是否甚至是用libdaemon构建的,但至少我有一个新的理论.:-)
小智 5
在我看来,这是由进程CROND(由crond生成的每个任务)等待stdin上的输入引起的,该输入通过管道传递到crontab中命令的stdout / stderr。这样做是因为cron能够通过邮件将结果输出发送给用户。
因此CROND正在等待EOF,直到用户命令及其所有产生的子进程关闭了管道。如果完成此操作,CROND会继续等待语句,然后消失的用户命令将消失。
因此,我认为您必须从管道中显式断开脚本中所有产生的子进程的连接(例如,将其重定向到文件或/ dev / null。
因此以下行应在crontab中工作:
* * * * * ( /tmp/launcher.sh /tmp/tester.sh &>/dev/null & )
Run Code Online (Sandbox Code Playgroud)