なるほどUnixプロセス ― Rubyで学ぶUnixの基礎
まだβ版ですが、面白そうだったので買ってみました。初代iPadのiBooks上で全152ページで値段が2,980(正式には3,360)円というのはちと高い気がしますが、原書が$27なのでまあしょうがないでしょう。
で、ざざっと読んでみた感想としては面白いですね。Unixのプロセスの話をRubyで学ぶようになっていてC言語でやるよりはRubyの方が抽象度が高いので比較的わかりやすいと思います。類書も無いような気がしますね。
シグナルのあたりとかパラパラと読んでいて、そういやfluentdだとどうなってんだっけと思いsupervisor.rbを読んでみました。
startメソッドはこんな感じになっています。fluentdを起動するとここが呼ばれます。
def start require 'fluent/load' @log.init start_daemonize if @daemonize install_supervisor_signal_handlers until @finished supervise do read_config change_privilege init_engine install_main_process_signal_handlers run_configure finish_daemonize if @daemonize run_engine exit 0 end end end
fluentdを起動するとsupervisorプロセスとその子プロセスであるワーカープロセス(メインプロセス)の2つのプロセスが起動します。
$ pgrep -f fluentd
とやると2つのプロセスのプロセスIDを表示することができます。
supervisorプロセスにシグナルハンドラを登録しているのがinstall_supervisor_signal_handlersメソッドです。
def install_supervisor_signal_handlers trap :INT do @finished = true if pid = @main_pid Process.kill(:INT, pid) end end trap :TERM do @finished = true if pid = @main_pid Process.kill(:TERM, pid) end end trap :HUP do $log.info "restarting" if pid = @main_pid Process.kill(:TERM, pid) end end trap :USR1 do @log.reopen! if pid = @main_pid Process.kill(:USR1, pid) end end end
メインプロセスにシグナルハンドラを登録しているのはinstall_main_process_signal_handlersメソッドです。
def install_main_process_signal_handlers trap :INT do Fluent::Engine.stop end trap :TERM do Fluent::Engine.stop end trap :HUP do # TODO end trap :USR1 do $log.info "force flushing buffered events" @log.reopen! Fluent::Engine.flush! end end
INTやTERMの場合はfluentdがstopします。
pkill -INT -f fluentd
とかやってみると確認できます。
一方で
pkill -HUP -f fluentd
とやるとfluentdが再起動します。
INT, TERMと違って@finishedがfalseのままなのでメインプロセスをkillしてもstartメソッド内のループは終了しないからですね。
pkill -USR1 -f fluentd
だとbufferをflushします。
詳細は本家のドキュメントを見るといいと思います。
Fluentd’s Signal Handling | Fluentd
ソースコードリーディングにはこちらが参考になると思います。
fluentd のソースを読む (1) - @kyanny's blog