/etc/init.d 脚本中对守护进程的调用被阻止,而不是在后台运行
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我最终在 bash init 脚本中重写了启动函数,并且我不再使用
daemon
了。我检查 pid 文件是否不存在(如果存在,只需写一个警告)。如果没有,我用
启动脚本。
我不知道这种方式是否安全(?),但它有效。
I finally re-wrote the start function in the bash init script, and I am not using
daemon
anymore.I check that the pid file is not existing already (if so, just write a warning). If not, I use
to start the script.
I don't know if it is safe this way (?) but it works.
守护进程的正确方法是让它自行与终端分离。这就是大多数大型软件套件的做法,例如 阿帕奇。
daemon
不执行您所期望的名称的基本原理,以及如何使 UNIX 进程分离到后台,可以在 此处,1.7 如何让我的程序像守护进程一样运行?有关此主题的进一步阅读: 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?For further reading on this topic: What's the difference between nohup and a daemon?
根据
man daemon
正确的语法是您的 init 脚本启动应该运行如下所示的内容:
According to
man daemon
correct syntax isYour init script startup should run something like:
正如这里所说,看来需要使用&将进程发送到后台。
守护进程不会为你做这件事。
As said here, it seems that the process needs to be sent to the background using &.
Daemon don’t do it for you.