ここに私が持っているものがあります。sysv init スクリプトもあります。Repo は GitHubにあります。また、私が見つけた他の解決策へのリンクを含む簡単なブログ投稿もあります。
実行できるデーモン プロセスは 1 つだけです。これは、他のほとんどの Linux デーモンと同様に、PID ロック ファイルによって管理されます。それを止めるには、
kill `cat /var/run/eg_daemon.pid`
実行中かどうかを確認するには:
ps -elf | grep `cat /var/run/eg_daemon.pid`
pidfile サブモジュールを使用すると、PID ファイルは自動的に管理されます。デーモンが停止すると、pidfile はクリアされます。init スクリプトについては、リンクされた GitHub リポジトリを参照してください。
Python デーモン コードは次のとおりです。
#!/usr/bin/env python3.5
import sys
import os
import time
import argparse
import logging
import daemon
from daemon import pidfile
debug_p = False
def do_something(logf):
### This does the "work" of the daemon
logger = logging.getLogger('eg_daemon')
logger.setLevel(logging.INFO)
fh = logging.FileHandler(logf)
fh.setLevel(logging.INFO)
formatstr = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
formatter = logging.Formatter(formatstr)
fh.setFormatter(formatter)
logger.addHandler(fh)
while True:
logger.debug("this is a DEBUG message")
logger.info("this is an INFO message")
logger.error("this is an ERROR message")
time.sleep(5)
def start_daemon(pidf, logf):
### This launches the daemon in its context
### XXX pidfile is a context
with daemon.DaemonContext(
working_directory='/var/lib/eg_daemon',
umask=0o002,
pidfile=pidfile.TimeoutPIDLockFile(pidf),
) as context:
do_something(logf)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Example daemon in Python")
parser.add_argument('-p', '--pid-file', default='/var/run/eg_daemon.pid')
parser.add_argument('-l', '--log-file', default='/var/log/eg_daemon.log')
args = parser.parse_args()
start_daemon(pidf=args.pid_file, logf=args.log_file)
完全を期すために、ここに init スクリプトを示します。「kill」は、実際には POSIX シグナルを送信するための単なる方法であることに注意してください。概要については、signal(7) のマニュアル ページを参照してください。python-daemon コンテキストはシグナルをキャッチし、ファイル記述子を完全に閉じてプロセスを終了し、PID ファイルを自動的に削除します。だから、それは本当にきれいな終了です。
デーモン構成のリロードを行うために、SIGUSR1 などをキャッチするコードを作成できます。Python でデーモンを停止するように書く利点はありません。
#!/bin/bash
#
# eg_daemon Startup script for eg_daemon
#
# chkconfig: - 87 12
# description: eg_daemon is a dummy Python-based daemon
# config: /etc/eg_daemon/eg_daemon.conf
# config: /etc/sysconfig/eg_daemon
# pidfile: /var/run/eg_daemon.pid
#
### BEGIN INIT INFO
# Provides: eg_daemon
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Short-Description: start and stop eg_daemon server
# Description: eg_daemon is a dummy Python-based daemon
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
if [ -f /etc/sysconfig/eg_daemon ]; then
. /etc/sysconfig/eg_daemon
fi
eg_daemon=/var/lib/eg_daemon/eg_daemon.py
prog=eg_daemon
pidfile=${PIDFILE-/var/run/eg_daemon.pid}
logfile=${LOGFILE-/var/log/eg_daemon.log}
RETVAL=0
OPTIONS=""
start() {
echo -n $"Starting $prog: "
if [[ -f ${pidfile} ]] ; then
pid=$( cat $pidfile )
isrunning=$( ps -elf | grep $pid | grep $prog | grep -v grep )
if [[ -n ${isrunning} ]] ; then
echo $"$prog already running"
return 0
fi
fi
$eg_daemon -p $pidfile -l $logfile $OPTIONS
RETVAL=$?
[ $RETVAL = 0 ] && success || failure
echo
return $RETVAL
}
stop() {
if [[ -f ${pidfile} ]] ; then
pid=$( cat $pidfile )
isrunning=$( ps -elf | grep $pid | grep $prog | grep -v grep | awk '{print $4}' )
if [[ ${isrunning} -eq ${pid} ]] ; then
echo -n $"Stopping $prog: "
kill $pid
else
echo -n $"Stopping $prog: "
success
fi
RETVAL=$?
fi
echo
return $RETVAL
}
reload() {
echo -n $"Reloading $prog: "
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status -p $pidfile $eg_daemon
RETVAL=$?
;;
restart)
stop
start
;;
force-reload|reload)
reload
;;
*)
echo $"Usage: $prog {start|stop|restart|force-reload|reload|status}"
RETVAL=2
esac
exit $RETVAL