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

Posted

技术标签:

【中文标题】在 /etc/init.d 脚本中调用守护进程被阻塞,不在后台运行【英文标题】:Call to daemon in a /etc/init.d script is blocking, not running in background 【发布时间】:2011-12-28 18:56:07 【问题描述】:

我有一个要守护的 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 文件是空的(或者只有换行符,daemon 没有返回 pid)。

有人知道我做错了什么吗?

编辑:也许我应该说我在 Red Hat 机器上。

Scientific Linux SL release 5.4 (Boron)

谢谢, 托尼

【问题讨论】:

您可以使用 inotify en.wikipedia.org/wiki/Inotify 通知您何时发生更改,而不是编写守护程序来轮询更改。它更容易编码,更高效,并且可以更快地查看更新。有许多 CPAN 模块可以与之交谈。 search.cpan.org/search?query=inotify&mode=all 谢谢,这是有用的信息,我一定会看看 Inotify。 @Schwern :这并没有改变我必须在后台运行守护进程等待 inotify 通知的事实,不是吗?? 确实如此。我无法帮助您了解 Redhat 上的 daemon 命令的详细信息。它因系统而异。 【参考方案1】:

根据man daemon正确的语法是

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

您的 init 脚本启动应该像这样运行:

daemon --pidfile $pidfile -- $exe

【讨论】:

谢谢 yko,但这不是因为我的“守护进程”用法说:daemon [+/-nicelevel] program。也许我们没有相同的版本。 @tony 我最终安装了daemon from libslack deamon @tony 指的是/etc/rc.d/init.d/functions 声明的那个【参考方案2】:

我终于在bash init脚本中重新编写了start函数,我不再使用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 &

启动脚本。

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

【讨论】:

我使用了类似的东西,但使用daemon 和 nohup 来提供脚本启动时显示的输出。这更像是一个视觉提示,因为只要 nohup 运行,[OK] 消息将始终返回 OK:以 daemon "nohup $exe >/dev/null 2>&1 &" 为例。 tony,当你的 shell 终止时,这个守护进程不会死吗?或者 nohup 会阻止这种情况发生吗? 是的,当shell终止时,nohup创建的进程仍然活着。 我尝试了 daemon/nohup 方法,但我无法以这种方式获取 PID。有什么想法吗? @Joe : shell 变量 '$!'是在后台启动的最后一个进程的 pid。对你的目的来说足够了吗?【参考方案3】:

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

【讨论】:

【参考方案4】:

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

daemon 背后的基本原理不符合您对它的名称的期望,以及如何使 unix 进程分离到后台,可以在 1.7 部分中找到here 如何让我的程序像守护进程一样行事?

仅仅在后台调用一个程序是不够的 这些长期运行的程序;没有正确分离 从启动它的终端会话中处理。此外,该 启动守护进程的传统方式是简单地发出命令 手动或从 rc 脚本;守护进程应该把自己 进入后台。

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

【讨论】:

以上是关于在 /etc/init.d 脚本中调用守护进程被阻塞,不在后台运行的主要内容,如果未能解决你的问题,请参考以下文章

Linux下怎么查看某个守护进程或者所有的守护进程?

Linux守护进程之systemd

Linux 超级守护进程 xinetd

启动脚本_《UNIX/LINUX 系统管理技术手册 第四版》

redis开机自动服务脚本

部署 CherryPy(守护进程)