我有一个Perl脚本来启动进程作为守护进程。但是,当我从cron调用它时,我会离开一个已经不复存在的过程。我把它剥离到一个最小的脚本,我开始'尾'作为守护进程的占位符:
use POSIX "setsid";
$SIG{CHLD} = 'IGNORE';
my $pid = fork();
exit(0) if ($pid > 0);
(setsid() != -1) || die "Can't start a new session: $!";
open (STDIN, '/dev/null') or die ("Cannot read /dev/null: $!\n");
my $logout = "logger -t test";
open (STDOUT, "|$logout")
or die ("Cannot pipe stdout to $logout: $!\n");
open (STDERR, "|$logout")
or die ("Cannot pipe stderr to $logout: $!\n");
my $cmd = "tail -f";
exec($cmd);
exit(1);
我用cron运行它并最终得到:
root 18616 18615 0 11:40 ? 00:00:00 [test.pl] <defunct>
root 18617 1 0 11:40 ? 00:00:00 tail -f
root 18618 18617 0 11:40 ? 00:00:00 logger -t test
root 18619 18617 0 11:40 ? 00:00:00 logger -t test
据我所知,它是记录器的管道,它不喜欢,如果我将STDOUT和STDERR发送到/ dev / null,则问题不会发生。
我做错了什么或这是不可能的? (CentOS 5.8)
谢谢,
leonstr
答案 0 :(得分:1)
这是导致它的管道。来自“Programming Perl”:
(在fork
上):
如果分叉子项继承了STDIN和STDOUT之类的系统文件描述符 连接到远程管道或插座,您可能必须在孩子中重新打开它们 到/ dev / null。那是因为即使父进程退出,孩子也会活着 使用那些文件句柄的副本。