Linux 在 /etc/init.d 脚本中调用守护进程被阻塞,不在后台运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8124345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Call to daemon in a /etc/init.d script is blocking, not running in background
提问by tony
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/
) :
我有一个想要守护进程的 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;
}
So this script basically prints something every 3 seconds.
所以这个脚本基本上每 3 秒打印一次。
Then, as I want to daemonize this script, I've also put this bash script (also called synpipe_server) in /etc/init.d/
:
然后,因为我想守护这个脚本,我也把这个 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 "" in
start)
start
;;
stop)
stop
;;
status)
status ${pname}
;;
restart)
restart
;;
*)
echo "Usage: service synpipe_server start
{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 :
所以,(如果我已经很好地理解了守护进程的文档)Perl 脚本应该在后台运行,/dev/null
如果我执行,输出应该被重定向到:
[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]#
But here is what I get instead :
但这是我得到的:
Scientific Linux SL release 5.4 (Boron)
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).
所以它启动了 Perl 脚本,但在不将它与当前终端会话分离的情况下运行它,我可以看到在我的控制台中打印的输出......这并不是我真正期望的。此外,PID 文件是空的(或者只有换行符,daemon没有返回 pid )。
Does anyone have any idea of what I am doing wrong ?
有没有人知道我做错了什么?
EDIT : maybe I should say that I am on a Red Hat machine.
编辑:也许我应该说我在 Red Hat 机器上。
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
}
Thanks, Tony
谢谢,托尼
采纳答案by tony
I finally re-wrote the start function in the bash init script, and I am not using daemon
anymore.
终于在bash init脚本里重新写了start函数,现在不用daemon
了。
nohup ${exe} >/dev/null 2>&1 &
I check that the pid file is not existing already (if so, just write a warning). If not, I use
我检查 pid 文件是否已经存在(如果存在,只需写一个警告)。如果没有,我用
daemon [options] -- [command] [command args]
to start the script.
启动脚本。
I don't know if it is safe this way (?) but it works.
我不知道这样是否安全 (?) 但它有效。
回答by yko
According to man daemon
correct syntax is
根据man daemon
正确的语法是
daemon --pidfile ${pidfile} -- ${exe}
Your init script startup should run something like:
您的 init 脚本启动应该运行如下:
##代码##回答by Thibault Deheurles
回答by MarkM
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.
守护进程的正确方法是让它自己从终端分离。大多数大型软件套件都是这样做的,例如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 herein section 1.7 How do I get my program to act like a daemon?
该原理背后daemon
不这样做,你会从它的名字会发生什么,以及如何使UNIX进程分离到背景中,可以发现这里在第1.7如何让我的程序作为一个守护进程?
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 itselfinto the background.
对于这些长时间运行的程序来说,简单地在后台调用一个程序是不够的;没有正确地将进程从启动它的终端会话中分离出来。此外,启动守护进程的传统方法是手动或从 rc 脚本发出命令;守护进程应该将自己置于后台。
For further reading on this topic: What's the difference between nohup and a daemon?
有关此主题的进一步阅读:nohup 和守护进程有什么区别?