デーモン化したい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はdaemonで返されません)。
誰かが私が間違っていることを知っていますか?
編集:たぶん私はRed Hatマシンを使用していると言う必要があります。
Scientific Linux SL release 5.4 (Boron)
ありがとう、トニー
ついに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 &
スクリプトを開始します。
この方法で安全かどうかはわかりませんが(?)、動作します。
プロセスをデーモン化する適切な方法は、プロセスをターミナルから切り離すことです。これは、たとえば Apache のように、最も大きなソフトウェアスイートが行う方法です。
daemon
の背後にある理論的根拠は、その名前から期待することをしていないこと、およびUNIXプロセスをバックグラウンドに切り離す方法については、 here セクションを参照してください)1.7プログラムをデーモンのように動作させるにはどうすればよいですか?
バックグラウンドでプログラムを呼び出すだけでは、これらの長期実行プログラムには実際には十分ではありません。これは、プロセスを開始したターミナルセッションからプロセスを正しく切り離しません。また、デーモンを起動する従来の方法は、コマンドを手動またはrcスクリプトから発行することです。デーモンはitselfをバックグラウンドに置くことが期待されています。
このトピックの詳細については、 Nohupとデーモンの違いは何ですか?
による man daemon
正しい構文は
daemon [options] -- [command] [command args]
あなたのinitスクリプトのスタートアップは次のようなものを実行するはずです:
daemon --pidfile ${pidfile} -- ${exe}