今さらながら
なぜ daemontools を使うのか - kazuhoのメモ置き場
これを読んで、
通常のプログラムをそのままデーモン化できるから
という記述にうんうんと頷いていた。1
今回は、daemontools もいいかもしれないけど God を使って daemon 作ろうぜって話。これは monit には真似できないよ。
cf. M/Monit | Wiki
Godでオレオレデーモンを作る
例えば以前作った Rswatch っていうログを監視するツールなんかも、一応 daemon のように動くけど、これ落ちたらどうすんのとか、システム起動時に自動的に起きるようにするのどうしよう、とかいろいろ管理しにくくて仕方なかった。デーモンを作ることは、実は 1)目的の動作を作り込むこと、2)デーモン化する処理を作り込むこと、の二つに分けられる。そう、2 は目的じゃない。期待する動作ではあるけれど。
God を使えば 2 の部分はすべて God 任せにできる。
また自分の中では daemon と言うとサーバとかこういう監視ツールをすぐに思い浮かべちゃうんだけど、別にそんな役に立つものばかりが daemon というわけじゃない。ここでは
とりあえず終了しないもの
は全部 daemon と呼ぶことにする。例えば twitter の bot なんかは daemon である。
Godを使った基本的なdaemon化の流れ
実は Ruby だけの話であれば別に God を使わなくても Process.daemon でも daemons でもいいのだが、これは後述することにして God の話を進める。
スクリプトを用意
まずは終了しないプログラムを作る。こんなものでもいい。
#! /usr/bin/env ruby
require 'logger'
i = 0
l = Logger.new( File.dirname( __FILE__ ) + '/counter.log' )
loop do
l.info( i )
i += 1
sleep 1
end
これを例えば counter.rb という名前で用意する。これを実行すると当然1秒ごとに延々と数字を数え上げていく動きをする。
tail -f counter.log
で、その様子を確認できる。わざわざ絶対パスにしているのは、
daemon 化したときにカレントディレクトリが変わってしまうから。
これはもうそういうものなので肝に命じておく。
godファイルを用意
同じディレクトリに以下の内容で God の設定ファイルを作る。
God.watch do |w|
w.name = 'counter'
w.interval = 5.seconds
w.start = "ruby #{File.dirname( __FILE__ ) + '/counter.rb'}"
w.behavior( :clean_pid_file )
w.start_if do |start|
start.condition( :process_running ) do |c|
c.running = false
end
end
end
これを counter.god のような名前で保存する。スクリプトのパスを絶対パスにしているのはさっきと同じ理由。あるいは実行するプラグラムを PATH の通ったところに置けばもう少し話は簡単。
xig_installer を作ったのは実はこのためである。
実行ファイルの場所が変わってしまったら God の設定ファイルをいちいち書き換えなくてはならない。これは面倒くさいし、まず忘れる。
※ ここでは ruby に PATH が通っていることを期待した書き方になっているが、FreeBSD + ports のようにデフォルトの PATH が /usr/bin で追加するプログラムがすべて /usr/local/bin に入る環境は、この部分もフルパスにしておくべき。
god 経由で起こす
まず -D を付けて起こす。
god -D -c counter.god
するとスクリプトを daemon 化する様子、状態を監視している様子がそのままターミナルに表示される。正常に daemon 化できて監視できていれば ^C で終了する。
このとき、daemon 化したスクリプトはそのまま動き続ける
が、慌てず
god -c counter.god
と打って god プロセスの daemon 化を行う。すると
今動いているプロセスをそのまま監視対象にできる
ので、この状態で
god stop counter
と打てば止められる。あるいは
god terminate
とすれば丸ごと全部終了できる。
どうだろう。
単に終了しないプログラムを作っただけなのに God を噛ませることでちゃんと daemon 化できている。2
また、ここまでの例はすべて Ruby で書いているが、daemon 化したいプログラムは何で書かれていても関係ない。Godにプロセスの起動順序を教えたい などで触れている tiarra は Perl 製だし、なんでもよい。
おまけ - Rubyでdaemonを作って管理するその他の方法
死活監視やリソース消費を監視して自動的に再起動、などの機能が要らない場合は以下のリンク先も参考になる。
- Ruby: daemon (Japanese)
- すごく丁寧で、Ruby 1.8 向けも含めて参考になる
- 僕たちが待ち望んでいたRubyスクリプトをデーモン化する方法 - (rubikitch loves (Emacs Ruby CUI))
- Ruby 1.8 も含めて楽をする方法
ただしこれらの情報だけでは作った daemon をコントロールすることができない。Rubyスクリプト限定でいいなら以下を使うと God より楽に管理できる。
これを使えば基本的には
Daemons.run(デーモン化したいスクリプトのファイル名)
だけで済む。
ま、もちろん監視はできないけど。