在/etc/init.d脚本中调用守护进程是阻塞的,而不是在后台运行

我有一个Perl脚本,我想要守护进程。 基本上这个perl脚本会每隔30秒读取一个目录,读取它find的文件,然后处理这些数据。 为了简单起见,可以考虑下面的Perl脚本(称为synpipe_server,这个脚本在/usr/sbin/有一个符号链接):

 #!/usr/bin/perl use strict; use warnings; my $continue = 1; $SIG{'TERM'} = sub { $continue = 0; print "Caught TERM signal\n"; }; $SIG{'INT'} = sub { $continue = 0; print "Caught INT signal\n"; }; my $i = 0; while ($continue) { #do stuff print "Hello, I am running " . ++$i . "\n"; sleep 3; } 

所以这个脚本基本上每3秒打印一次。

然后,因为我想守护这个脚本,我也把这个bash脚本(也称为synpipe_server)放在/etc/init.d/

 #!/bin/bash # synpipe_server : This starts and stops synpipe_server # # chkconfig: 12345 12 88 # description: Monitors all production pipelines # processname: synpipe_server # pidfile: /var/run/synpipe_server.pid # Source function library. . /etc/rc.d/init.d/functions pname="synpipe_server" exe="/usr/sbin/synpipe_server" pidfile="/var/run/${pname}.pid" lockfile="/var/lock/subsys/${pname}" [ -x $exe ] || exit 0 RETVAL=0 start() { echo -n "Starting $pname : " daemon ${exe} RETVAL=$? PID=$! echo [ $RETVAL -eq 0 ] && touch ${lockfile} echo $PID > ${pidfile} } stop() { echo -n "Shutting down $pname : " killproc ${exe} RETVAL=$? echo if [ $RETVAL -eq 0 ]; then rm -f ${lockfile} rm -f ${pidfile} fi } restart() { echo -n "Restarting $pname : " stop sleep 2 start } case "$1" in start) start ;; stop) stop ;; status) status ${pname} ;; restart) restart ;; *) echo "Usage: $0 {start|stop|status|restart}" ;; esac exit 0 

所以,(如果我已经很好的理解了守护进程的文档),Perl脚本应该在后台运行,输出应该被redirect到/dev/null如果我执行:

 service synpipe_server start 

但是,这是我所得到的:

 [root@master init.d]# service synpipe_server start Starting synpipe_server : Hello, I am running 1 Hello, I am running 2 Hello, I am running 3 Hello, I am running 4 Caught INT signal [ OK ] [root@master init.d]# 

所以它启动Perl脚本,但运行它,而不从当前的terminal会话中分离出来,我可以看到输出打印在我的控制台中……这不是我所期待的。 而且,PID文件是空的(或者只有一个换行符, 守护进程没有返回pid)。

有谁知道我做错了什么?

编辑:也许我应该说,我在一个红帽机器上。

 Scientific Linux SL release 5.4 (Boron) 

谢谢,Tony

Solutions Collecting From Web of "在/etc/init.d脚本中调用守护进程是阻塞的,而不是在后台运行"

我终于在bash初始化脚本中重新编写了启动函数,而且我不再使用daemon

 start() { echo -n "Starting $pname : " #daemon ${exe} # Not working ... if [ -s ${pidfile} ]; then RETVAL=1 echo -n "Already running !" && warning echo else nohup ${exe} >/dev/null 2>&1 & RETVAL=$? PID=$! [ $RETVAL -eq 0 ] && touch ${lockfile} && success || failure echo echo $PID > ${pidfile} fi } 

我检查该pid文件是不是已经存在(如果是这样,只是写一个警告)。 如果没有,我使用

  nohup ${exe} >/dev/null 2>&1 & 

启动脚本。

我不知道这是否安全(?),但它的工作原理。

对进程进行守护进程的正确方法是让它独立于终端。 这就是大多数更大的软件套件,例如apache 。

daemon没有做你期望从它的名字,以及如何使unix进程分离背景,可以在这里找到1.7我如何让我的程序像一个守护进程?

简单地在后台调用一个程序对于这些长时间运行的程序来说是不够的。 这不会正确地从启动它的终端会话中分离进程。 此外,启动守护进程的传统方式是简单地手动或从rc脚本发出命令; 守护进程有望把自己置于后台。

有关此主题的进一步阅读: nohup和守护进程之间有什么区别?

根据man daemon正确的语法是

 daemon [options] -- [command] [command args] 

您的init脚本启动应该运行如下所示:

 daemon --pidfile ${pidfile} -- ${exe} 

正如这里所说的,似乎这个过程需要使用&发送到后台。 守护进程不会为你做。