デーモンプロセス制御のシェル関数を使ったデーモン登録

感想おまちしてます!

スクリプトをバックグラウンドで動作するデーモンとして登録する方法。
「/etc/init.d/crond」を参考に調べた。

ここで使われるフォルダは以下になる。

  • /proc ・・・プロセス情報が入っている
  • /var/lock/subsys ・・・ lockファイル作成ディレクトリ
  • /var/run ・・・ プロセスIDが書かれたファイルを書き出す場所
スポンサーリンク

/etc/init.d/functions

「/etc/init.d/functions」にはデーモンの制御に便利なシェル関数が書かれている。プロセスの確認、開始メッセージ表示など、普通のシェルでも使える内容になっている。

checkpid PID

指定されたPIDで起動していれば0、それ以外は1。「/proc」以下にPIDのフォルダがあるかで判断している。

daemon {+/-nicelevel} {program}

プログラムを開始する。

killproc [-d delay] {program} [signal]

プログラムを停止する。「/var/run」にあるPIDファイルは削除してくれる

pidfileofproc {program}

プログラムのPIDをみつける。「/var/run/{program}.pidのみ確認する。
PIDファイルがあれば0・・・なんだろうけど、return 1をしていないため、絶対0がかえってしまう。バグ?
以下の文で、PIDが不正かどうかチェックしている。

# First try "/var/run/*.pid" files
if [ -f /var/run/$base.pid ] ; then
local line p pid=
read line < /var/run/$base.pid
for p in $line ; do
[ -z "${p//[0-9]/}" -a -d /proc/$p ] && pid="$pid $p"
done
if [ -n "$pid" ]; then
echo $pid
return 0
fi
fi

プロセスIDを確認する以下の部分では、まず0から9の数値をすべて空文字におきかえることができるかと、/proc/にプロセスIDのフォルダが存在するかで確認している。

[ -z "${p//[0-9]/}" -a -d /proc/$p ] && pid="$pid $p"

プロセスIDが空文字の場合はのちの「if [ -n “$pid” ]; then」で引っかかる。

pidofproc {program}

プログラムのPIDをみつける。「/var/run/{program}.pidをまず探し、それでなければ「pidof」コマンドを使って探す。存在すれば0を返す。それ以外は1。

status {program}

プログラムのステータスを確認する。

echo_success

成功メッセージ表示。

echo_failure

失敗メッセージ表示。

echo_passed

パスメッセージ表示。

echo_warning

警告メッセージ表示。

confirm

実行を確認できる。Yならば0、Nならば1、Continueならば2

デーモン作成

デーモン呼び出しする「fujidaemond」とスクリプト本体である「fujidaemon」を作成する。

デーモン呼び出しスクリプト

ここにスクリプト本体呼び出しを書いてもよい。

#! /bin/bash
#
# fujidaemond          Start/Stop the fujidaemon daemon.
#
# chkconfig: 2345 90 60
# description: sample program
# processname: fujidaemon
# config: none
# pidfile: /var/run/fujidaemon.pid

# Source function library.
. /etc/init.d/functions

# See how we were called.

prog=”fujidaemon”

start() {
echo -n $”Starting $prog: ”
if [ -e /var/lock/subsys/$prog ]; then
if [ -e /var/run/$prog.pid ] && [ -e /proc/`cat /var/run/$prog.pid` ]; then
echo -n $”cannot start $prog: $prog is already running.”;
failure $”cannot start $prog: $prog already running.”;
echo
return 1
fi
fi
daemon ./fujidaemon &
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog;
return $RETVAL
}

stop() {
echo -n $”Stopping $prog: ”
if [ ! -e /var/lock/subsys/$prog ]; then
echo -n $”cannot stop $prog: $prog is not running.”
failure $”cannot stop $prog: $prog is not running.”
echo
return 1;
fi
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog;
return $RETVAL
}

rhstatus() {
status $prog
}

restart() {
stop
start
}

reload() {
echo -n $”Reloading $prog daemon configuration: ”
killproc $prog -HUP
RETVAL=$?
echo
return $RETVAL
}

case “$1″ in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
rhstatus
;;
condrestart)
[ -f /var/lock/subsys/$prog ] && restart || :
;;
*)
echo $”Usage: $0 {start|stop|status|reload|restart|condrestart}”
exit 1
esac

exit 0

スクリプト本体

役割的にはデーモン呼び出し部分でやるのは変かなーと思ったので、プロセスIDの出力などはスクリプト本体で行うようにした。
とりあえず、なんもしないスクリプト。

#!/bin/bash

prog=fujidaemon

touch /var/run/$prog
echo $$ > /var/run/$prog

while true; do
sleep 1
done