(私家版 daemontools FAQ) 1. 初歩的な質問

back


daemontools ってなに?

daemontools は UNIX のデーモンを起動・終了・再起動したり、ログを とったりするためのプログラム群だよ。 svscan, multilog, svc, svstat などのプログラムからなっている。


どんな人におすすめ?

こんな経験があるひとに:

  1. ログが増えすぎて /var が溢れたことがある (あるいは、溢れそうになってヒヤリとしたことがある)。
  2. サービスによって、/etc/syslog.conf をいちいち 書き換えるのはめんどう。facility や priority を うまく指定しないと大変。
  3. ログのローテーションをするスクリプトを書いて cron に仕掛けた。 けどうまく動くかどうか不安。
  4. なんか知らんけど syslogd がうまく動かなくて、大量のログを 取りこぼした。(syslogd はログの受け渡しに AF_UNIX ドメインの ソケットを使っていて、 ときどきデータがうまく渡らないことがあるらしい。)
  5. /sbin/init.d/something start を実行したのにデーモンが開始しなかった。 前回、異常終了したのでロックファイル (pid ファイル) が 残っていたんだ。ちくしょう。
  6. いつも新しいサービスを追加するたびに、 ロックファイルを確認する起動スクリプトを書いて、 それを init.d に置いて、そこへ各 rc?.d から リンクをはってる。そして時にうまく動かない。まったく。
  7. root になって ps auxww をたくさん実行してる。 ときどき設定変更を反映させるために kill -HUP したら終了してしまうデーモンがいて、 ムカついた。
  8. あるデーモンがやたらとメモリを食ったり CPU に負荷を かけたりするんだけど、なんとかなんないの?

これを使うとどんないいことがあるの?

いくつかあるよ (まだあるかもしれない):

  1. まず、syslog とは違ってソケットの代わりにパイプを 使っているから、ログが確実にとれる。
  2. ログの容量を監視してくれる。ログのローテーションは 日付ではなく、ある一定容量に達したかどうかによって行われる。
  3. サービスの追加・削除が簡単にできる。 システム起動時に自動的に開始するか否かも簡単に指定できる。
  4. サービスを監視するためのロックファイルを作らなくてすむ。
  5. デーモンの pid を直接調べなくてもシグナルが送れる。 daemontools を使って走らせた各デーモンは pid ではなく 名前で指定でき、複数のデーモンにシグナルを送ったりも できる。
  6. 起動するデーモンごとに limit をかけられる。 これによってメモリ使用量やユーザ権限を制限できる。

daemontools はどんなデーモンでも管理できるの?

daemontools が管理できるデーモンは、必ず フォアグラウンドで走るものにかぎる。 なかには勝手に自らを fork させて、バックグラウンドに移行してしまう ようなものもあり、これらのデーモンは管理できないことがある (ただしこれらを無理矢理フォアグラウンドで走らせる fghack というツールが用意されているが、すべてがこれで OK という わけではない)。

D. J. Bernstein さんの 作ったプログラム、qmail, djbdns, tcpserver, publicfile などは、 どれも daemontools で管理できるようになっている。だから DJB のプログラムを使っている人は daemontools をインストールすることを すすめます。


daemontools はデーモンをどのように管理しているの?

daemontools の中心部分は supervise プログラムだ。 これは 1つのデーモンプロセスを「監督 (supervise)」する プログラムで、デーモン1つごとにひとつの supervise が 起動される。


その supervise プログラムはなにをするの?

supervise はデーモンを制御する、いわば“手綱”プログラムだ。 supervise はデーモンが走っているときも、止まっているときも、 つねに走りつづけていて、デーモンの挙動を監視し、svc プログラムからの 通信をうけてデーモンを制御する。 supervise は子プロセスとしてサービス用の デーモンを exec するので、デーモンの pid はつねに supervise によって 握られていることになる。デーモンが終了すると (あるいは強制的に 終了させられると) supervise はまた同じプログラムを exec する。 これを永遠にくり返す。なお、supervise はふつう root 権限で走る。


それで、どうやってデーモンに 簡単にシグナルが送れるようになるの?

ひとつの supervise (つまり、ひとつのサービス) は それ専用のディレクトリをひとつ使う (そして、このパス名は あらかじめ決め打ちだ)。ここには supervise と 通信するためのチャネル (実際には 名前つきパイプ) が用意されていて、 svc プログラムを使うことで、このチャネルから supervise に対してデーモンにシグナルを送るよう指示できる。 デーモンは supervise の子プロセスだから、supervise は 自分の子を exec したときの pid を覚えていて、それに シグナルを送ることができるわけだ。


まだよくわかんない。 supervise は結局デーモンなんじゃないの?
それって手動で走らせなきゃいけないわけ?

じつは superviseプログラム は svscan というプログラムによって 自動的に走らされる。また svscan は 5秒おきに新しい supervise用 ディレクトリをスキャンするから、サービスを新しく追加するのも 簡単だよ。


なんかディレクトリがいっぱい出てきて混乱した。

daemontools は、サービス管理用のディレクトリ・ツリーを使う。 ふつう、daemontools 用のトップレベルのディレクトリは /service にする習慣だ (こうしておくとあとあと便利だということがわかる)。 このディレクトリは、たとえば次のような構成になっている:

/service           (svscan がスキャンするディレクトリ)
/service/qmail     (supervise が読むディレクトリ、
                    qmail というサービスの設定を含んでいる)
/service/qmail/log (supervise が読むディレクトリ、
                    qmail というサービスのログ記録に関する設定)
/service/finger    (supervise が読むディレクトリ、
                    finger というサービスの設定を含んでいる)
/service/login     (supervise が読むディレクトリ、
                    login というサービスの設定を含んでいる)
このシステムでは qmail, finger, login という 3つのサービスを daemontools で走らせている。さらにサービス qmail はログを残すように なっている。ログを残すためにはそれ専用の supervise が走らなきゃいけないので、 結局 4つの supervise が走ることになるわけだ。 各 supervise は /service の直下にある qmail, finger, login そして qmail/log を読む。 daemontools でのプロセスの親子関係とディレクトリの親子関係は 似ている。以下の図をみてちょうだい。


図1・daemontools のプロセスの関係


図2・daemontools が使うディレクトリ構造

これらのディレクトリには、実際のデーモンプログラムをフォアグラウンドで exec するために、かならず run というファイル名のスクリプトを置く (この名前は固定)。 実はこれが supervise が実行するプログラムなんだ。run スクリプト の中では必ず exec でデーモンを起動しなきゃいけない。これによって run のプロセスがオーバーライドされ、supervise が run の pid を使ってデーモンを制御できるようになるから。

さらに supervise は各ディレクトリ内に supervise/ という専用ディレクトリを 自分で作成し、そこに通信用のパイプをおく。svc を使うと、このパイプに アクセスできる。これによって supervise を制御し、つまりはデーモンを 制御できる。このとき svc には /service 直下のディレクトリ名を 指定するので、これら /service 直下のディレクトリを サービスと同じ名前にしておけば、 サービス名によってデーモンを制御できることになるわけ。 さらにシェルから

 $ svc -t /service/*
などという技も使えるよ。

じゃあ svscan はどうやって走らせるの。

これはメタ・デーモンで、これだけはシステム起動時に 明示的に (rc 内あるいは手動で) 走らせるしかない。 しかしこれさえ走らせておけば、あとは svscan がその管理下の デーモンを supervise 経由で自動的に走らせてくれるよ。


svscan は何をするの?

svscan はつぎのようにして起動する。いちど起動したら終了しない:

$ svscan dir
svscan は 5秒に 1回、 引数 dir の直下にあるサブディレクトリをスキャンする。 慣習では dir/service になっているが省略可能ではない。 新たなディレクトリを発見したら、そのディレクトリ名を引数にして supervise を起動する。svscan は、ディレクトリを再帰的にスキャンするのでは ない。ただし log という名前のディレクトリだけは別である。

注意: 「新たなディレクトリ」とは 「i-node が新しい」ということであって、「新しい名前の」ディレクトリではない。 svscan は現在あるサブディレクトリの i-node をすべて記憶しているが、 その名前は記憶していない。

svscan は「スキャンして、新しいディレクトリがあれば supervise を 起動する」という動作をひたすら繰り返すだけなので、たとえ supervise が 終了してもディレクトリがあるかぎり (最長で) 5秒後には再び起動される。


ログはどうやって残すの?

daemontools を使う環境では、 ログをとるプログラムには multilog を使う。これは標準入力をログファイルに 吐くもので、規定の容量に達したログは自動的にローテートし、 古いログは自動的に削除する。multilog もまたデーモンの 一種なので、supervise によって監督する。あるサービスの ディレクトリを /service/hoge とすると、そのログ用の ディレクトリは必ず /service/hoge/log にする約束になっている。 log という名前は固定だ。

svscan はサービスのディレクトリをスキャンするのだが、その ディレクトリの sticky bit (ls したときに t と表示される) が立っていて、さらにその中に log ディレクトリがある 場合は同時にログ用の supervise も走らせる。 つまり、ひとつのサービスでデーモン用とログ記録用の 2つの supervise が走ることになるんだ。この 2つの supervise 間には、 svscan によって「デーモン用 → ログ用」の方向のパイプが つくられ、ログ用 supervise はデーモン用 supervise の標準出力を 受けとる。

じつは svscan は supervise の終了を検知するようになっており、 既知のディレクトリに対しては何度 supervise を実行しても 同じパイプのファイル記述子を使うようになっている。これによって、 たとえばデーモン用の supervise が再起動しても、log 用の supervise は そのまま継続してこの新しい supervise からログを取ることができる。


svc は何をしているの?

svc は 名前つきパイプ を介して supervise にメッセージを送る、 ただそれだけのプログラムだ。たとえば

 $ svc -t /service/qmail
を実行すると、svc は /service/qmail/supervise ディレクトリにある 名前つきパイプ に「t」という文字を書き込む。これを supervise が受けとって、 qmail デーモンに TERM シグナルを送るわけだ。

インストールの方法は?

滝沢さんが書かれている、daemontools HOW-TO

が役に立ちます。インストールから 使い方までくわしく書かれているよ。同じく滝沢さんによる daemontools マニュアル日本語訳 も参照。


daemontools は完全に syslogd の代用品になるの? New!

ならない。他の多くのプログラム (たとえば sendmail) と同じく、 syslogd はひとつのプログラムに多くの機能を詰めこみすぎている。 これが堅牢さの低下につながっている。 multilog は、syslogd のすべての機能を含んでいるわけではなく、 標準出力(あるいは他のファイル記述子)にログを吐くデーモンのログしか 取らない。したがって:

カーネルの出力や UDP からの出力を取るプログラムは 今のところまだ daemontools には含まれていない。 そのため、カーネルやルータのログ、その他 libc の syslog() 関数を使っている デーモンのログを取るためにやはり syslog が必要。 ただし syslog は信頼性の面から問題があるので、やはりなるべく multilog を使えるものは multilog で残したほうがいいよ。デーモンによっては ログを syslog 経由で吐くか、標準エラー出力に吐くかを選べるものもある (たとえば socks5LPRng に付属の lpd など)。

(2000/11/9 追記) syslogd を置きかえるための logkit と呼ばれるプログラムをつくりました。 これは syslog がやっている、AF_UNIX ドメインの /dev/log (BSD系 の場合は /var/run/log) というソケットを介した文字列を受け渡しを 横取りして、それをただ標準入力に流すだけの簡単なプログラムです。 multilog と組み合わせれば syslogd の代わりになります。 まだテスト段階ですが、新山のマシン (Linux-2.2) では、syslogd (と klogd) は これと daemontools で完全に置き換えられており、今のところうまく動いています (klogd のほうはただ /proc/kmsg を cat しているだけ)。


Last modified: Wed Sep 26 18:26:18 2001
Yusuke Shinyama