Godで簡単daemonize

今さらながら

なぜ 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を作って管理するその他の方法

死活監視やリソース消費を監視して自動的に再起動、などの機能が要らない場合は以下のリンク先も参考になる。

ただしこれらの情報だけでは作った daemon をコントロールすることができない。Rubyスクリプト限定でいいなら以下を使うと God より楽に管理できる。

これを使えば基本的には

Daemons.run(デーモン化したいスクリプトのファイル名)

だけで済む。

ま、もちろん監視はできないけど。

  1. 本当に理解できているか自信がなかったのでブログのコメントでその確認もさせてもらった 

  2. 細かい daemon の定義は調べるといろいろ出てくるよ! 

More

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Develop Document Jekyll