新しいサービスをログ記録なしで走らせる手順は?
たとえばサービス名 finger を新しく走らせるとする。svscan は すでに走っていて、/service 以下のディレクトリを見張っていると する:
bash-2.03# ls -l /service/finger/supervise/ total 1 prw------- 1 root system 0 Apr 26 13:54 control -rw------- 1 root system 0 Apr 26 13:42 lock prw------- 1 root system 0 Apr 26 13:42 ok -rw-r--r-- 1 root system 18 Apr 26 13:54 status
#!/bin/sh
exec env - \
/usr/local/bin/tcpserver -u 65534 -g 65534 0 79 \
/usr/local/etc/in.fingerd
注意: ここではこのシェルスクリプトのプロセス
自体がデーモンプロセスに override されるよう、
デーモンの起動には
必ず exec を使うこと。またデーモンはフォアグラウンドで
走りつづけなければならない。
しかしデーモンによっては (というか、現在使われている
デーモンのほとんどが)、いきなり自分自身を fork して
バックグラウンドに移行してしまうようにできている。このような
デーモンには、
fghack
を使ってみよう。
$ svc -d /service/finger
を実行すれば tcpserver は止まる (down)。ここで、
$ svc -u /service/finger
を実行すれば、tcpserver はふたたび走りだす (up)。
新しいサービスをログ記録つきで走らせる手順は?
サービス qmail を新しくログつきで走らせるとしよう。 /service/qmail というディレクトリを使うとする。ログを 残すためには、このディレクトリの sticky bit が立っていなければ ならないのだが、いきなり
$ mkdir /service/qmail (×)などとするのはマズい。svscan は新しくディレクトリを つくる瞬間にしか sticky ビットを見てくれない からだ。 このときにまだ sticky ビットが立っていないと、あとで /service/qmail/log ディレクトリを作っても、svscan は 何もしない (svscan を再起動すれば話は別だけど)。 なので、sticky ビットを立てるまでは /service 以下に qmail ディレクトリを置かないほうが得策だ。
svscan が /service 以下を検査するのは 5秒に 1回なので、
$ mkdir /service/qmail; chmod +t /service/qmailとシェルで入力して一瞬でやってしまうという手もある。 しかしこれも、完全にうまくいくとは保証されない。 よりまともな方法としては、次の 2つがある。
$ mv /service/.qmail /service/qmail
を実行すればいい。
ここでは後者の方法でやってみよう:
$ cd /service
$ mkdir .qmail
$ mkdir .qmail/log
$ chmod +t .qmail
$ mv .qmail qmail
svscan が sticky bit を検知し、
$ svc -d /service/qmail
$ svc -d /service/qmail/log
を実行し、どちらのデーモンも開始しないようにしておく。
この例でもわかるように、デーモン用の supervise と
ログ用の supervise は別々に制御しなければならない。
/service/qmail/run:
#!/bin/sh
exec env - PATH="/var/qmail/bin:/usr/local/bin:/usr/bin:/bin" \
qmail-start ./Mailbox
/service/qmail/log/run: (なお、この例は daemontools HOW-TO の startup script の例 から引用させていただきました)
#!/bin/sh
exec \
setuidgid qmaill \
multilog t ./main \
-'* status: *' \
-'* starting delivery *' \
-'* delivery * success*' \
-'* delivery * failure*' \
-'* new msg *' \
-'* info msg *' \
-'* end msg *' \
-'* bounce msg *' \
-'* delivery * deferral: Sorry,_I_couldn't_find_any_host_by_that_name*' \
-'* delivery * deferral: Sorry,_I_wasn't_able_to_establish_an_SMTP_*' \
./alert \
'-*' '+* status: *' =status
multilog は daemontools に含まれているログ記録用デーモンだ。 上のスクリプトでは、setuidgid を使ってこのデーモンを qmaill というユーザで走らせている。multilog はログファイルの 行頭にタイムスタンプを付けくわえたり、必要な行だけをパターンマッチで 記録する (あるいは記録しない) ことが可能だ。 multilog の詳しい使い方については multilog のマニュアル を参照のこと。
$ chown qmaill.nofiles /service/qmail/log
を実行しよう。
$ svc -u /service/qmail/log
$ svc -u /service/qmail
を実行する。これで qmail デーモンが走り出し、
/service/qmail/log/main/current にログが現れるはずだ。
multilog で t オプションを指定すると、ログの各行の先頭に
TAI64N 形式のタイムスタンプがつく。これの見方は
ログの変なタイムスタンプはなに? の項を参照。
このログの変なタイムスタンプはなに?
ログの各行頭に現れる @4000000039c97bf53afbe444 などという 文字列はタイムスタンプだよ。 これは TAI64N 形式というもので、うるう秒を考慮した 時間の表現形式になっている。TAI形式については http://tehanu.hpcl.titech.ac.jp/time/utctai.html に 説明がある。
TAI64N 形式をふつうの時刻として見るためには、daemontools に ついてくる tai64nlocal コマンドを使おう。これは標準入力から受けとったテキストの行頭の TAI64N 形式 タイムスタンプを、ローカル時刻で人間が読みやすい形式にして出力して くれるよ。以下のようにして使う:
$ tai64nlocal < /service/qmail/log/mail/current
デーモンを再起動/kill -HUP したい
svc を使おう。
$ svc -t /service/サービス名とすれば、そのサービスを行っているデーモンに TERM シグナルが 送られる。その後 supervise はすぐにこれを起動しなおすので、 結果として再起動したことになる。HUP シグナルを送るには、
$ svc -h /service/サービス名を実行する。svc にはまだほかにもいろいろな オプションがある。 http://www.emaillab.org/djb/tools/daemontools/svc.html を 参照のこと。
サービスを止めたい/再開したい
これも svc を使う。
$ svc -d /service/サービス名 (停止, down) $ svc -u /service/サービス名 (開始, up)
しかし、システム起動時には、svscan によって起動された supervise はデフォルトでデーモンを up してしまう。 これを防ぐためには、ディレクトリ /service/サービス名 に down という ファイルをつくっておく。
$ touch /service/サービス名/downとすればよい。中身はなくてもファイルの存在だけがスイッチになる。 supervise はその起動時にこのファイルを発見すると、 デフォルトでサービスを down のままにしておく。 supervise が down ファイルの有無を 検査するのは、supervise の起動時だけなので注意すること。 いったん supervise が起動してしまったら、デーモンの 停止・再開には svc を使おう。
サービスを完全に廃止したいんだけど
サービスを完全に廃止して supervise を止めるには、 まず /service/サービス名 というディレクトリを 最初に svscan の目が届かないところに置く必要がある。そうしないと supervise を止めてもすぐにまた svscan が supervise を 走らせてしまうからだ。といっても、サービス用のディレクトリを いきなり rm -rf などで消してしまうのは危険なので、 以下のようにする。たとえば /service/qmail を廃止することを 考えてみよう:
$ mv /service/qmail /service/.qmail
/service ディレクトリから
どこか他のディレクトリにリンクをはっているなら、
それを消すだけでよい。
$ svc -x /service/.qmail/log
$ svc -x /service/.qmail
-x オプションは、supervise に
「デーモンが終了したらきみも一緒に終了せよ」と指示する。
これでデーモン用の supervise とログ用の supervise に
それぞれ終了が宣告された。ディレクトリの名前は変わっているが、
svc はそのまま通用する (なぜならこのプログラムは、ただ
与えられたディレクトリ名に「/supervise」という文字列を
追加し、そこの名前つきパイプを操作するだけだからだ)。
注意:
デーモン用 supervise とログ用 supervise は
それぞれ別個に指示してやらねばならない。
$ svc -d /service/.qmail/log
$ svc -d /service/.qmail
これでデーモンは両方止まり、supervise も終了した。
svstat /service/.qmail を実行してみよう。
「supervise not running」と表示されるはずである。