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

发布于 2024-12-15 10:28:58 字数 2435 浏览 0 评论 0原文

我有一个 Perl 脚本,我想对其进行守护进程。基本上,这个 perl 脚本将每 30 秒读取一个目录,读取它找到的文件,然后处理数据。为了简单起见,请考虑以下 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 脚本应该在后台运行,如果我执行,输出应该重定向到 /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 脚本,但运行它而不需要将其从当前的终端会话,我可以看到控制台中打印的输出......这并不是我所期望的。此外,PID 文件是空的(或者只有换行符,守护进程没有返回 pid)。

有谁知道我做错了什么?

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

Scientific Linux SL release 5.4 (Boron)

谢谢, 托尼

I have a Perl script that I want to daemonize. Basically this perl script will read a directory every 30 seconds, read the files that it finds and then process the data. To keep it simple here consider the following Perl script (called synpipe_server, there is a symbolic link of this script in /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;
}

So this script basically prints something every 3 seconds.

Then, as I want to daemonize this script, I've also put this bash script (also called synpipe_server) in /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

So, (if I have well understood the doc for daemon) the Perl script should run in the background and the output should be redirected to /dev/null if I execute :

service synpipe_server start

But here is what I get instead :

[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]# 

So it starts the Perl script but runs it without detaching it from the current terminal session, and I can see the output printed in my console ... which is not really what I was expecting. Moreover, the PID file is empty (or with a line feed only, no pid returned by daemon).

Does anyone have any idea of what I am doing wrong ?

EDIT : maybe I should say that I am on a Red Hat machine.

Scientific Linux SL release 5.4 (Boron)

Thanks,
Tony

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

世界等同你 2024-12-22 10:28:58

我最终在 bash init 脚本中重写了启动函数,并且我不再使用 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 &

启动脚本。

我不知道这种方式是否安全(?),但它有效。

I finally re-wrote the start function in the bash init script, and I am not using daemon anymore.

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
}

I check that the pid file is not existing already (if so, just write a warning). If not, I use

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

to start the script.

I don't know if it is safe this way (?) but it works.

故事与诗 2024-12-22 10:28:58

守护进程的正确方法是让它自行与终端分离。这就是大多数大型软件套件的做法,例如 阿帕奇

daemon 不执行您所期望的名称的基本原理,以及如何使 UNIX 进程分离到后台,可以在 此处1.7 如何让我的程序像守护进程一样运行?

仅仅在后台调用一个程序并不足以满足
这些长时间运行的程序;不能正确分离
来自启动它的终端会话的进程。另外,
启动守护进程的传统方法是简单地发出命令
手动或通过 rc 脚本;守护进程预计将自身
进入后台。

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

The proper way to daemonize a process is have it detach from the terminal by itself. This is how most larger software suites do it, for instance, apache.

The rationale behind daemon not doing what you would expect from its name, and how to make a unix process detach into the background, can be found here in section 1.7 How do I get my program to act like a daemon?

Simply invoking a program in the background isn't really adequate for
these long-running programs; that does not correctly detach the
process from the terminal session that started it. Also, the
conventional way of starting daemons is simply to issue the command
manually or from an rc script; the daemon is expected to put itself
into the background.

For further reading on this topic: What's the difference between nohup and a daemon?

锦上情书 2024-12-22 10:28:58

根据 man daemon 正确的语法是

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

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

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

According to man daemon correct syntax is

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

Your init script startup should run something like:

daemon --pidfile ${pidfile} -- ${exe}
撩起发的微风 2024-12-22 10:28:58

正如这里所说,看来需要使用&将进程发送到后台。
守护进程不会为你做这件事。

As said here, it seems that the process needs to be sent to the background using &.
Daemon don’t do it for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文