回答: いくつかの理由があります。
サービスの導入や除去が簡単にできること。 /service と init.d を使えば、 いくつかのファイルを一元化されたディレクトリにリンクするだけで 新しいサービスを作成したことになります。 また、これらのファイルを削除すると、そのサービスを 除去したことになります。 これによって作業は簡単に自動化できます。
これとは逆に、 inittab や rc.local を使った場合、 新しいサービスを作成するには一元化されたファイルに いくつかの行を追加することになります。 またサービスを除去するときは、それらの追加された行をつきとめ 削除しなくてはいけません。 こうなると、作業の自動化はずっと難しくなります: ファイルを編集するための移植性の高いツールは存在していません。 そのため、ほとんどのパッケージでは、この編集作業は ユーザに任される形になっています。
最初のサービス立ち上げが簡単にできること。 /service を使うと 一度サービスを作成すれば、それは 5秒以内に自動的に開始されます。
これとは逆に、 inittab や init.d、 rc.local を使った場合、 サービスを開始するには余計なコマンドを実行しなくてはいけません。
確実に再起動されること。 /service や inittab を使った場合、 もしお使いのデーモンが死んでも、それは自動的に再起動されます。
これとは逆に、 init.d や rc.local を使った場合は デーモンは監視されません。 たとえば前回起動したデーモンが一時的にシステムのメモリを ほとんど使い果たしてしまった場合、新しいデーモンは起動に失敗するでしょう。 このような場合、システム管理者は問題発生に気づいてから それを手動で再起動させる必要があります。
簡単、確実なシグナル送信。 /service を使えば、 システム管理者はデーモンを制御するのに svc を 使うことができます。たとえば:
「きれいな」プロセス状態。 /service や inittab を使えば、 システム管理者がサービスを再起動させても そのサービスをシステムブート時と同様の「きれいな」状態から 始めることができます。
これとは逆に、 init.d や rc.local を使った場合は、 状態を元に戻すために多大な労力が必要です。 環境変数や使用できるリソースの上限、端末制御など。 プログラマーは、いつもこれらのことに苦しめられています。 たとえ (異なるプロセス状態をもつ) 別システムへの移植を 考えなくてもです。 そしてシステム管理者はデーモンを再起動するときに 不可解な事故に出くわすことになります。
移植性。 /service を使えば、 あなたのプログラムはあらゆるシステム上で同じやり方を 使って動かすことができます: Linux, BSD, Solaris など。
これとは逆に、 inittab や init.d、 rc.local を 使っている場合、やり方はシステムによって違います。 たとえばいくつかのシステムでは init.d がなかったり、 あっても場所がまちまちだったりします。 これは複数のプラットフォームを管理している システム管理者にとって、たいへん腹立たしいことです。
回答: サービス用のディレクトリ中に唯一必要なコンポーネントは ひとつの実行可能ファイル ./run です。 これはデーモンをフォアグラウンドで走らせるもので、 そのデーモンが終了すればこれも終了します (訳注: この説明はおかしい、正確にはプロセスが オーバーライドされるので、./run がデーモン自身になる)。 ふつう ./run のパーミッションは 755 であり、 そのディレクトリ自身のパーミッションも 755 になっています。
典型的な ./run はシェルスクリプトです。たとえば:
#!/bin/sh echo starting exec clockspeedここでの exec は、 自分自身を clockspeed によって置き換えるよう sh に指示します。 これによって、システム管理者は svc を使うことで clockspeed にシグナルを直接送ることができます。
指定されたディレクトリ中にあるファイルに従って環境変数を設定するには、 envdir が使えます。通常このディレクトリは ./env です:
#!/bin/sh exec envdir ./env ./run2これによって、デーモンの設定を簡単かつ自動化されたやり方で おこなうことができます。
その他の ./run 用の役に立つツールとしては envuidgid, setuidgid, softlimit, および setlock があります。
一般に、シェルのパイプラインを使うのはいい方法ではありません:
#!/bin/sh generate-crucial-data | log-crucial-dataこの場合、もし log-crucial-data が起動に失敗したら、 generate-crucial-data によってすでにパイプに 吐かれているデータはすべて捨てられてしまいます。 この問題を解消するため ログの分離 を使いましょう。
回答: まず、お使いのサービス用ディレクトリを sticky (パーミッション 1755) にします。これはバージョン 0.75 以前の daemontools との互換性のためです。 つぎに、サービス用ディレクトリの中に ./log サブディレクトリを 作ります。そしてロギング用プログラムを走らせる ./log/run スクリプトを置きます。
svscan はお使いのデーモンからロギング用プログラムへと 流れるパイプを作成します。たとえば、./run が 以下のようになっていたとしましょう:
#!/bin/sh exec generate-crucial-dataいっぽう ./log/run はこうなっていたとします:
#!/bin/sh exec log-crucial-dataすると、 generate-crucial-data からの 標準出力は log-crucial-data の標準入力に流れます。 また、それぞれのプログラムは独立に監督 (supervise) されます: つまり log-crucial-data が死んでも自動的に再起動されるし、 generate-crucial-data が死んでも自動的に再起動されるわけです。
./log/run で使うロギング用プログラムの一般的な 選択としては、 multilog があります:
#!/bin/sh exec multilog t ./mainこの例ではログの各行の行頭にタイムスタンプが追加され、 結果は自動的にローテートされるログ用ディレクトリ ./log/main に保存されます。
ロギング用プログラムを root 以外のアカウントで走らせるには、 setuidgid を使います:
#!/bin/sh exec setuidgid cruxlog multilog t ./mainただし、この場合 ./log/main ディレクトリはその ユーザの所有にしなければいけません。 multilog には ./log/main を作成できる権限は ないからです。
お使いのデーモンがログメッセージをファイル記述子 2 (標準エラー出力) に 吐き出す場合は、デーモン用の ./run スクリプト中でこれを ファイル記述子 1 (標準出力) にリダイレクトする必要があります:
#!/bin/sh exec 2>&1 exec envuidgid tinydns envdir ./env softlimit -d300000 /usr/local/bin/tinydns
回答: 最良の解はデーモンを修正することです。 デーモンをバックグラウンドに移行させるのは、どれも悪い ソフトウエアデザインです。
fghack を使うと、デーモンによっては強制的にフォアグラウンドで走らせることが できます:
#!/bin/sh echo starting exec fghack inetdでも fghack を使った場合は、 supervise がシグナルを送ることはできません。気をつけてください。
fghack はそのデーモンからのパイプを作成し、 そのパイプが閉じられるまでデータを読みつづけます。 通常、デーモンの子プロセスはすべてそのデーモンが開いた パイプを継承しますから、パイプが閉じられた時はそれらが すべて終了したときだ、ということになります。
しかしながら、そのデーモンが余分なファイル記述子をすべて 閉じてしまうといったことをする場合、fghack は すぐに終了してしまいます。 これらのデーモンのうちいくつかはファイル記述子 0 を (使わないにもかかわらず) 開いたままにしておくので、
#!/bin/sh exec fghack baddaemon <&-こうすればうまくいくかもしれません。
回答: 最良の解はデーモンを修正することです。 自分が作成してもいないプロセスグループにシグナルを送るプログラムは、 許されるものではありません。
pgrphack を使えば、デーモンを新しいプロセスグループで走らせることができます:
#!/bin/sh echo starting exec pgrphack pppd nodetach call myisp
Answer: まず ./run.new を作ります。 つぎにそれをアトミックに ./run.new から ./run へ リネームします。そのあと
svc -t .を実行して、デーモンに TERM シグナルを送ってください。 デーモンが終了すると supervise は新しい ./run を 実行します。
決まった ./run を直接編集するやり方は安全ではありません。 supervise はいつでも ./run を再実行する 可能性があるからです。システムも、いつリブートするかわかりませんしね。
多くのロギング用プログラムは、 TERM を受けとった際に未処理の入力データを ぜんぶ捨ててしまうので気をつけてください。 multilog はこのあたりを心得ていて、 終了する前に読み込んだすべてのものを処理するようになっています。
回答: あなたのサービス用ディレクトリへのシンボリックリンクを、 /service 中に作成してください:
ln -s /etc/sshd /service/sshdsvscan は 5秒以内に、自動的 sshd をスタートさせます。
回答:
cd /service/telnetd rm /service/telnetd svc -dx . log
日本語訳: 新山 祐介 yusuke @ cs . nyu . edu