我有一个crontab,看起来像:
SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ 0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null &
尽可能简单吧?
我刚刚测试的zdaemon.php是:
#!/usr/bin/php while(true){ sleep(1); } ?>
无论什么时候它运行它挂起像:
root 15532 0.0 0.1 57228 1076 ? Ss 19:09 0:00 crond root 16681 0.0 0.1 72196 1428 ? S 21:46 0:00 crond root 16682 0.0 0.0 0 0 ? Zs 21:46 0:00 [bash]root 16683 0.0 0.5 54800 5740 ? S 21:46 0:00 /usr/bin/php /var/www/html/private/fivemin/zdaemon.php root 16687 0.0 0.1 72196 1428 ? S 21:47 0:00 crond root 16688 0.0 0.0 0 0 ? Zs 21:47 0:00 [bash] root 16689 0.0 0.5 54800 5740 ? S 21:47 0:00 /usr/bin/php /var/www/html/private/fivemin/zdaemon.php
这一天我一直在撞墙挡住我的大脑.谁看过这个吗?有什么想法吗?
这是对以下内容的引用:Init.d脚本挂起
一个僵尸进程不一定本身是一件坏事.它表示子进程已经死亡,并且父进程尚未获得其状态(使用wait()
或相关的系统调用).
发生的事情如下 - 从它启动的脚本cron
感兴趣stderr(如果脚本失败它可以通过电子邮件发送给你),因此它会创建一个管道,它附加脚本的stderr来写入结尾(文件描述符2) ).然后cron
坐在读取管道的读取端,等待脚本退出并读取eof(read()
零字节) - 然后重新获取脚本的返回状态.
在您的示例中,生成的守护程序继承了stderr文件描述符,因此当中间shell退出(并且变得不存在)时,管道将由守护程序保持打开状态.因此,cron
永远不会读取eof,因此永远不会获得返回状态.
解决方案是确保您的守护程序的stderr关闭.这可以通过以下方式实现:
0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null 2>&1 &
这将写两个 标准输出和标准错误,以/dev/null