在 /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 脚本中调用守护进程被阻塞,不在后台运行的主要内容,如果未能解决你的问题,请参考以下文章