capistrano3-unicorn
capistrano + rails + unicornという構成の時に、unicornを色々と操作するやつ。
unicornを再起動したり色々としてくれる。
https://github.com/tablexi/capistrano3-unicorn/blob/a4adb59031b001a9cd8f9dce5f4beb3200c80f8d/lib/capistrano3/tasks/unicorn.rake
killとは
システムコールのkillは、任意のプロセス・グループもしくはプロセスにシグナルを送るのに使われる。
始めてkillというコマンドを知った時にはみんな誤解したはず。killはプロセスに命令を送るコマンド(殺すやつじゃない)
シグナルを全部追うと大変なのでcapistrano3-unicornが発行している物だけ抜粋
kill -0
0はプロセスがいるかどうか確認するだけ。
プロセスがいない場合には、エラーが返っている。
$ ps aux | grep [u]nicorn
ubuntu 1886 0.0 2.7 390020 111700 ? Sl 12:21 0:05 unicorn master -c /xxx/unicorn/development.rb -E development -D
ubuntu 1899 0.0 2.8 402224 117272 ? Sl 12:22 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -E development -D
$ kill -0 1886
$ echo $?
0
$ kill -0 1888
-su: kill: (1888) - No such process
$ echo $?
1
[code抜粋] unicornのstart時にそもそもunicornが動いているかどうかを確認する為に使われている。
desc "Start Unicorn"
task :start do
on roles(fetch(:unicorn_roles)) do
within current_path do
if test("[ -e #{fetch(:unicorn_pid)} ] && kill -0 #{pid}")
info "unicorn is running..."
else
with rails_env: fetch(:rails_env) do
execute :bundle, "exec unicorn", "-c", fetch(:unicorn_config_path), "-E", fetch(:unicorn_rack_env), "-D", fetch(:unicorn_options)
end
end
end
end
end
kill -s QUIT
キーボードによる中止。QUITを送れはプロセスは止まる。
$ ps aux | grep [u]nicorn
ubuntu 1886 0.0 2.7 390020 111700 ? Sl 12:21 0:05 unicorn master -c /xxx/unicorn/development.rb -E development -D
ubuntu 1899 0.0 2.8 402224 117272 ? Sl 12:22 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -E development -D
$ kill -s QUIT 1886
$ ps aux | grep [u]nicorn | wc -l
0
[code抜粋] unicornをstopする時に使われている。
desc "Stop Unicorn (QUIT)"
task :stop do
on roles(fetch(:unicorn_roles)) do
within current_path do
if test("[ -e #{fetch(:unicorn_pid)} ]")
if test("kill -0 #{pid}")
info "stopping unicorn..."
execute :kill, "-s QUIT", pid
else
info "cleaning up dead unicorn pid..."
execute :rm, fetch(:unicorn_pid)
end
else
info "unicorn is not running..."
end
end
end
end
kill -s HUP
制御端末(controlling terminal)のハングアップ検出、
または制御しているプロセスの死
killでシグナルを受け取った場合の挙動は、書かれているプログラムにより異なるが、HUPを受け取るとconfigを読み直してリロードする設計が多く見られる。
unicornもそのようになっている。
親プロセスにHUPを送るとconfigを読み直して子プロセスが新しく起動している(pidが変わっている)
$ ps aux | grep [u]nicorn
ubuntu 2056 42.1 2.7 323096 111164 ? Sl 14:25 0:04 unicorn master -c /xxx/unicorn/development.rb -D -E development
ubuntu 2061 0.0 2.6 323096 105848 ? Sl 14:25 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -D -E development
$ kill -s HUP 2056
$ ps aux | grep [u]nicorn
ubuntu 2056 6.0 2.7 388632 111244 ? Sl 14:25 0:04 unicorn master -c /xxx/unicorn/development.rb -D -E development
ubuntu 2066 0.0 2.6 388632 105856 ? Sl 14:26 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -D -E development
[code抜粋] unicornのreloadで使われている
desc "Reload Unicorn (HUP); use this when preload_app: false"
task :reload do
invoke "unicorn:start"
on roles(fetch(:unicorn_roles)) do
within current_path do
info "reloading..."
execute :kill, "-s HUP", pid
end
end
end
kill -s USR2
ユーザー定義シグナル。
これも実装側で挙動を決める。unicornのは合いUSR2を受け取ると親プロセスごと新しく生まれ変わる。
実際に打ってみると確かに、親プロセスのpidが変わっている。
$ ps aux | grep [u]nicorn
ubuntu 2056 2.1 2.7 388632 111244 ? Sl 14:25 0:04 unicorn master -c /xxx/unicorn/development.rb -D -E development
ubuntu 2066 0.0 2.6 388632 105856 ? Sl 14:26 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -D -E development
$ kill -s USR2 2056
$ ps aux | grep [u]nicorn
ubuntu 2073 32.3 2.7 389848 111600 ? Sl 14:29 0:05 unicorn master -c /xxx/unicorn/development.rb -D -E development
ubuntu 2084 0.0 2.5 390000 105020 ? Sl 14:29 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -D -E development
[code抜粋] unicornのrestartで使われている
desc "Restart Unicorn (USR2); use this when preload_app: true"
task :restart do
invoke "unicorn:start"
on roles(fetch(:unicorn_roles)) do
within current_path do
info "unicorn restarting..."
execute :kill, "-s USR2", pid
end
end
end
kill -s TTIN / TTOU
バックグランドプロセスの端末入力 / 出力
unicornに送ってみるとなかなか面白く、子プロセスが増えたり減ったりする。
これは相当便利ではないか!
でも、TTINで生まれた子プロセスだけ設定が新しいとか、起きそう。
$ kill -s TTIN 2073
$ ps aux | grep [u]nicorn
ubuntu 2073 0.5 2.7 389848 111632 ? Sl 14:32 0:05 unicorn master -c /xxx/unicorn/development.rb -D -E development
ubuntu 2084 0.0 2.5 390000 105020 ? Sl 14:32 0:00 unicorn worker[0] -c /xxx/unicorn/development.rb -D -E development
ubuntu 2103 0.0 2.5 389980 104968 ? Sl 14:48 0:00 unicorn worker[1] -c /xxx/unicorn/development.rb -D -E development
$ kill -s TTOU 2073
$ ps aux | grep [u]nicorn
ubuntu 2073 0.5 2.7 389848 111640 ? Sl 14:32 0:05 unicorn master -c config/unicorn/development.rb -D -E development
ubuntu 2084 0.0 2.5 390000 105020 ? Sl 14:32 0:00 unicorn worker[0] -c config/unicorn/development.rb -D -E development
[code抜粋] 当然unicornでプロセス増やしたり減らしたりする時に使う。
desc "Add a worker (TTIN)"
task :add_worker do
on roles(fetch(:unicorn_roles)) do
within current_path do
info "adding worker"
execute :kill, "-s TTIN", pid
end
end
end
desc "Remove a worker (TTOU)"
task :remove_worker do
on roles(fetch(:unicorn_roles)) do
within current_path do
info "removing worker"
execute :kill, "-s TTOU", pid
end
end
end
end
まとめ
unicornが受け取るシグナルとその挙動を知っていれば、緊急時にちょっとプロセス増やすとか減らすとか、設定を読み直すとかがさくっと出来るので知っていて損はなさそうですね。