daemontools
daemontools とは、Unixのデーモンのコントロール(起動、終了、再起動)、ログ取得などのプログラムを集めたユーティリティです。デーモンプログラムの作成やデーモンの設置が簡単になります。デーモンプログラムが落ちても、自動で起動します。標準エラー出力がロギングされ、ログローテーションが自動で行われます。FreeBSDだけでなく、Linuxでも使用できます。フォアグラウンドで実行できるプログラムがdaemontoolsの対称です。
読み方
- daemontools
- でーもん つーるず
概要
daemontoolsは、memcachedやnodoe.jsなどのプログラムなどの制御に向いています。そういったプログラム達は、自身が落ちてしまったときに、自主的に上がってきません。死活監視を行いながら、落ちたプロセスを自動起動するプログラムが必要になります。その役目をdaemontoolsは行うことができます。memcachedを複数起動したいときにも簡単に対応できます。
daemontools の svscan をデーモン化するには、daemonコマンドで実現します。
daemontoolsのコマンド
daemontoolsには、いろいろなコマンドが用意されています。
svscan
svscan は、次のような動作をします。
- svscanがディレクトリを監視します。
- 新しいディレクトリがあれば、supervise プロセスを起動します。
- superviseが終了している場合は、 supervise を起動します。
- .(ドット)ではじまるディレクトリは、無視します。
supervise
supervise は、サービスのプロセスを起動します。
- run を実行します。
- run が終了したら、 run を起動します。
- supervise の起動時に、 down があれば、 run を実行しません。
multilog
ログの収集は、 multilog コマンドを使用します。
- 標準入力をロギングします。
- タイムスタンプをつけられます。
- ログを自動で切り替えられます。
- 指定されたサイズを超えたら、ローテーションされます。
- 指定された個数以上のログを削除します。
setuidgid
uidとguidを指定したuidとgidにセットします。補助グループ権限は、削除されます。 サービスのユーザーやロギングのためのmultilogのユーザーを設定します。 runやlog/runのスクリプトのexecで使用します。
#!/bin/sh exec setuidgid nobody /path/to/command arguments
インストール
pkgコマンドでインストールする場合
sudo pkg install daemontools
ファイル
daemontools-0.76_16: /usr/local/bin/envdir /usr/local/bin/envuidgid /usr/local/bin/fghack /usr/local/bin/multilog /usr/local/bin/pgrphack /usr/local/bin/readproctitle /usr/local/bin/setlock /usr/local/bin/setuidgid /usr/local/bin/softlimit /usr/local/bin/supervise /usr/local/bin/svc /usr/local/bin/svok /usr/local/bin/svscan /usr/local/bin/svscanboot /usr/local/bin/svstat /usr/local/bin/tai64n /usr/local/bin/tai64nlocal /usr/local/etc/rc.d/svscan /usr/local/man/man8/envdir.8.gz /usr/local/man/man8/envuidgid.8.gz /usr/local/man/man8/fghack.8.gz /usr/local/man/man8/multilog.8.gz /usr/local/man/man8/pgrphack.8.gz /usr/local/man/man8/readproctitle.8.gz /usr/local/man/man8/setlock.8.gz /usr/local/man/man8/setuidgid.8.gz /usr/local/man/man8/softlimit.8.gz /usr/local/man/man8/supervise.8.gz /usr/local/man/man8/svc.8.gz /usr/local/man/man8/svok.8.gz /usr/local/man/man8/svscan.8.gz /usr/local/man/man8/svscanboot.8.gz /usr/local/man/man8/svstat.8.gz /usr/local/man/man8/tai64n.8.gz /usr/local/man/man8/tai64nlocal.8.gz /usr/local/share/licenses/daemontools-0.76_16/LICENSE /usr/local/share/licenses/daemontools-0.76_16/PD /usr/local/share/licenses/daemontools-0.76_16/catalog.mk
設定
/etc/rc.conf , rc.conf.local, /etc/rc.conf.d/svscan などに設定できます。
# svscan_enable Set to "YES" to run svscan. # svscan_servicedir The directory containing the various service. # directories to be monitored. Professor Daniel J. # Bernstein recommends "/service", but the FreeBSD # port has a default of "/var/service" instead, which # is consistent with the FreeBSD filesystem hierarchy # guidelines as described in the hier(7) manual page. # svscan_logdir If set, then svscan will not log its output through # readproctitle, but through multilog instead, and # the logs will be placed in the specified directory. # The FreeBSD port default is to run svscan through # readproctitle. # svscan_lognum The number of logfiles that multilog will keep if # svscan_logdir is set; the multilog default is 10. # svscan_logmax The maximum logfile size for multilog if svscan_logdir # is set; the multilog default is 99999. svscan_enable="YES" svscan_servicedir=/path/to/service # svscan_logdir # svscan_lognum # svscan_logmax
svscanのコントロール
起動
sudo /usr/local/etc/rc.d/svscan start
停止
sudo /usr/local/etc/rc.d/svscan stop
再起動
sudo /usr/local/etc/rc.d/svscan restart
ステータス
sudo /usr/local/etc/rc.d/svscan status
コマンドの終了を待つ
sudo /usr/local/etc/rc.d/svscan poll
サービスが有効か確認する
サービスが有効な場合は、0、そうでなければ、1を返します。コマンドは、何も表示しません。
sudo /usr/local/etc/rc.d/svscan enabled
rc.confの設定を表示します
サービスの制御に使われるrc.conf変数を表示します。
sudo /usr/local/etc/rc.d/svscan rcvar
はじめてのdaemontools
ファイルとディレクトリの設置
mkdir -p service/foo/log chmod +t service/foo
service/foo/run
デーモンにしたいプログラムを指定します。
#!/bin/sh exec /tmp/foo # vim: filetype=sh
service/foo/log/run
ロギングに使用するプログラムです。
#!/bin/sh exec multilog t ./main # vim: filetype=sh
/tmp/foo
stdoutとstderrにメッセージを出して、カウントが30を超えたら、終了してしまうプログラムです。
/* * main.c * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <err.h> int main(int argc, char *argv[]) { ssize_t c = 0; for(;;){ puts("Hoge"); warnx("Hello"); fflush(stderr); fflush(stdout); c++; sleep(1); if (c > 30) { puts("bye-bye"); exit(EXIT_FAILURE); } } exit(EXIT_SUCCESS); }
コンパイルします。
$ cc -o /tmp/foo main.c
実行する
サービスを開始するには、svscan にディレクトリを指定して、起動します。svscanは、指定されたディレクトリのサブディレクトリを読み、サービスを起動します。svscanは、デーモンプログラムではありません。
$ svscan service
C-c で停止できます。
プロセスツリー
svscanを実行すると、以下の様なプロセスツリー(htopの表示の抜粋です)になります。
1232 kaworu 121 0 62028 8348 0 S 0.0 1.7 0:30.63 │ ├─ -zsh 65867 kaworu 120 0 12312 1408 0 S 0.0 0.3 0:00.00 │ │ ├─ svscan service 65869 kaworu 121 0 8172 1384 0 S 0.0 0.3 0:00.00 │ │ │ ├─ supervise log 65871 kaworu 120 0 12280 1420 0 S 0.0 0.3 0:00.00 │ │ │ │ └─ multilog t ./main 65868 kaworu 120 0 8172 1384 0 S 0.0 0.3 0:00.00 │ │ │ └─ supervise foo 65872 kaworu 120 0 12260 1384 0 S 0.0 0.3 0:00.00 │ │ │ └─ /tmp/foo
プロセスの確認
以下は、実行中の状態です。
$ svstat service/foo service/foo: up (pid 66630) 12 seconds
プロセスが起動していないときは、以下の様なメッセージになります。
$ svstat service/foo service/foo: supervise not running
サービスの停止や起動
実行中のサービスの起動や停止は、svcコマンドで行います。 svcには、いくつものオプションがあります。起動と停止のオプションは以下の通りです。
- -u
- 起動
- -d
- 停止
$ svstat service/foo service/foo: up (pid 67004) 31 seconds $ svc -d service/foo $ svstat service/foo service/foo: down 2 seconds, normally up $ svc -u service/foo $ svstat service/foo service/foo: up (pid 67027) 2 seconds
ログファイルの時間を読めるようにする
ログは、このような形で記録されています。これだと時間がよくわかりません。
$ head ./service/foo/log/main/@4000000053895ad80f103574.u @4000000053895a2e1ef54524 Hoge @4000000053895a2f1ff776cc Hoge @4000000053895a3021686bec Hoge @4000000053895a312211aff4 Hoge @4000000053895a3222bba7ac Hoge @4000000053895a33256bc3ec Hoge @4000000053895a34285971e4 Hoge @4000000053895a352af959b4 Hoge @4000000053895a362be1fc64 Hoge @4000000053895a372dcca5c4 Hoge
tai64nlocalコマンドで時間をヒューマンリーダブル(人間がわかる)にできます。
$ tai64nlocal < ./service/foo/log/main/@4000000053895ad80f103574.u |head 2014-05-31 13:27:16.519390500 Hoge 2014-05-31 13:27:17.536311500 Hoge 2014-05-31 13:27:18.560491500 Hoge 2014-05-31 13:27:19.571584500 Hoge 2014-05-31 13:27:20.582723500 Hoge 2014-05-31 13:27:21.627819500 Hoge 2014-05-31 13:27:22.676950500 Hoge 2014-05-31 13:27:23.720984500 Hoge 2014-05-31 13:27:24.736230500 Hoge 2014-05-31 13:27:25.768386500 Hoge
node.js
#!/bin/sh exec setuidgid nobody /usr/local/bin/node /home/nodejs/http.js # vim: filetype=sh
memcached
#!/bin/sh exec setuidgid nobody /usr/local/bin/memcached -m 1024 -c 10240 -p 11211 -u nobody # vim: filetype=sh
エラー
svc: warning: unable to control service/foo: supervise not running
おそらく、svscanが動いていません。
$ svc -u service/foo svc: warning: unable to control service/foo: supervise not running
関連項目
- service
- daemon
- daemontools
ツイート