我有一个我想要守护的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)。
有没有人知道我做错了什么?
编辑:也许我应该说我在Red Hat机器上。Scientific Linux SL release 5.4 (Boron)
谢谢, 贝
答案 0 :(得分:17)
我终于在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 &
启动脚本。
我不知道这种方式是否安全(?)但它有效。
答案 1 :(得分:2)
守护进程的正确方法是将其与终端分离。这就是大多数大型软件套件的用途,例如apache。
daemon
背后的基本原理var count = 0;
$("#add").click(function(){
count++;
$("#numberFields").append('<input type="button" id="addThisNumber'+ count +'">');
//Handler 1
$("#numberFields").on('click', "#addThisNumber"+count, function(){
console.log("Handler 1" + count);
});
});
//Handler 2
$("#numberFields").on('click', "#addThisNumber"+count, function(){
console.log("Handler 2" + count);
});
没有按照你的名字做的,以及如何让unix进程分离到后台,可以在 1.7中找到here的基本原理让我的程序像守护进程一样?
在后台简单地调用程序并不适合 这些长期运行的计划;没有正确分离的 从启动它的终端会话开始。而且, 启动守护进程的传统方法就是发出命令 手动或从rc脚本;守护进程应该放置本身 进入后台。
有关此主题的进一步阅读:What's the difference between nohup and a daemon?
答案 2 :(得分:0)
根据man daemon
正确的语法是
daemon [options] -- [command] [command args]
您的init脚本启动应该运行如下:
daemon --pidfile ${pidfile} -- ${exe}
答案 3 :(得分:-1)
如上所述here,似乎需要使用&amp;将进程发送到后台。 守护进程不会为你做。