2011-11-14 48 views
21

我有一个Perl脚本,我想要守护进程。基本上这个Perl脚本会每隔30秒读取一个目录,读取它找到的文件,然后处理数据。为了保持它的简单这里考虑以下的Perl脚本(称为synpipe_server,有这个脚本的/usr/sbin/符号链接):在/etc/init.d脚本中调用守护进程阻塞,不在后台运行

#!/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 

所以,(如果我有很好的理解进行守护的DOC) Perl脚本应该在后台运行,输出应该被重定向到/dev/null如果我执行:

service synpipe_server start 

但这里是我所得到的,而不是:

[[email protected] 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 ] 
[[email protected] init.d]# 

因此,它启动Perl脚本,但不从当前终端会话中分离它而运行它,并且我可以看到输出结果打印在控制台中......这实际上并不是我期望的。而且,PID文件是空的(或者只有换行符,没有由守护程序返回的pid)。

有没有人有任何想法我做错了什么?

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

Scientific Linux SL release 5.4 (Boron) 

感谢, 托尼

+3

而不是写一个守护进程来轮询更改,你可以使用的inotify http://en.wikipedia.org/wiki/Inotify更改时通知你已经发生了。编码更容易,效率更高,并且可以更快地看到更新。有许多CPAN模块可以与之交谈。 http://search.cpan.org/search?query=inotify&mode=all – Schwern

+0

谢谢,这是有用的信息,我一定会看看Inotify。 – tony

+0

@Schwern:这并不改变我必须在后台运行守护进程等待inotify通知的事实,否? – tony

回答

15

我终于重新写的在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 & 

启动脚本。

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

+2

我使用了类似的东西,但是在nohup旁边使用'daemon'来提供脚本启动时显示的输出。它更像是一个视觉提示,因为只要没有运行,[OK]消息就会一直返回OK: 'daemon“nohup $ {exe}>/dev/null 2>&1&”' 例如,以 为例。 – Rohaq

+0

tony,当你的shell终止时,这个守护进程不会死掉吗?还是nohup阻止? – Mark

+0

是的,当shell结束时,nohup创建的进程仍然存在。 – tony

0

根据man daemon正确的语法是

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

你的初始化脚本启动应运行类似:

daemon --pidfile ${pidfile} -- ${exe} 
+3

感谢yko,但这不是因为我的'守护进程'用法说:'daemon [+/- nicelevel] {program}'。也许我们没有相同的版本。 – tony

+0

@tony你能解决命令使用问题吗? –

+0

@tony我最终安装了[libslack守护进程](http://libslack.org/daemon/#download) –

0

如上所述here,似乎该进程需要使用&发送到后台。 守护进程不会为你做。

1

将进程进行守护进程的正确方法是让它从终端本身分离。这是大多数更大的软件套件的做法,例如,apache

背后daemon的理由不这样做,你会从它的名字会发生什么,以及如何使UNIX进程分离到背景中,可以发现在部分1.7 here如何让我的程序,就像一个守护进程采取行动?

在后台简单地调用程序是不是真的足够 这些长时间运行的程序;它不会从启动它的终端会话中正确分离 进程。而且,启动守护进程的传统方式是手动或通过rc脚本发出命令 ;该守护进程有望将本身放入后台中

有关此主题的进一步阅读:What's the difference between nohup and a daemon?

相关问题