以前の投稿 (環境変数にパスワードを埋め込んでdeployするまで)
Ruby on Railsで githubなどにcommitしたくないパスワードなどを環境変数に設定してcapistranoでdeployする方法
http://qiita.com/kenjiszk/items/2e45660ce3b46596dfa1
自前で、unicorn起動時に環境変数をよんでから実行していた。
unicorn:restartでは環境変数をよみ直してくれない
unicornにUSR2を送ってみる
unicorn:restartは内部的にUSR2を送ってホットデプロイしているのでそれを観察する
unicornのシグナルに関しての詳細はこちら。
http://qiita.com/kenjiszk/items/7c6edc7f579ab068591a
元のプロセス
pid 237の親に二つ子プロセスがいる状態。
$ pstree -anp; ps aux | grep unicorn
bash,1
|-sshd,35
|-nginx,44
| `-nginx,45
`-ruby,237
|-{ruby},260
|-{ruby},261
|-{ruby},265
|-ruby,269
| `-{ruby},271
|-ruby,274
| `-{ruby},276
`-{ruby},275
app 237 0.5 3.9 519760 159992 ? Sl 22:37 0:09 unicorn master -c config/unicorn.rb -D -E development
app 269 0.0 3.7 519760 152916 ? Sl 22:37 0:00 unicorn worker[0] -c config/unicorn.rb -D -E development
app 274 0.0 3.7 519760 152916 ? Sl 22:37 0:00 unicorn worker[1] -c config/unicorn.rb -D -E development
app 311 0.0 0.0 8860 644 ? S+ 23:05 0:00 grep --color=auto unicorn
kill -s USR2 237 してみる
親にUSR2を送ってみる
すると新しい親(pid312)が、シグナルが送られたプロセスの子供として生まれる
$ pstree -anp; ps aux | grep unicorn
bash,1
|-sshd,35
|-nginx,44
| `-nginx,45
`-ruby,237
|-{ruby},260
|-{ruby},261
|-{ruby},265
|-ruby,269
| `-{ruby},271
|-ruby,274
| `-{ruby},276
|-ruby,312 /path/to/app/shared/bundle/ruby/2.2.0/bin/unicorn -c config/unicorn.rb -D -E development
| `-{ruby},315
`-{ruby},313
app 237 0.5 3.9 585296 159996 ? Sl 22:37 0:09 unicorn master (old) -c config/unicorn.rb -D -E development
app 269 0.0 3.7 519760 152916 ? Sl 22:37 0:00 unicorn worker[0] -c config/unicorn.rb -D -E development
app 274 0.0 3.7 519760 152916 ? Sl 22:37 0:00 unicorn worker[1] -c config/unicorn.rb -D -E development
app 312 54.0 0.5 89600 21940 ? Rl 23:06 0:01 ruby /path/to/app/shared/bundle/ruby/2.2.0/bin/unicorn -D -E development
app 318 0.0 0.0 8860 644 ? S+ 23:06 0:00 grep --color=auto unicorn
新プロセスが子供を作る
新しい親がスレッド作ったりして色々と頑張り始める
$ pstree -anp; ps aux | grep unicorn
bash,1
|-sshd,35
|-nginx,44
| `-nginx,45
`-ruby,237
|-{ruby},260
|-{ruby},261
|-{ruby},265
|-ruby,269
| `-{ruby},271
|-ruby,274
| `-{ruby},276
|-ruby,312 /path/to/app/shared/bundle/ruby/2.2.0/bin/unicorn -c config/unicorn.rb -D -E development
| |-{ruby},315
| |-{ruby},329
| |-{ruby},330
| `-{ruby},334
`-{ruby},313
app 237 0.5 3.9 585296 159996 ? Sl 22:37 0:09 unicorn master (old) -c config/unicorn.rb -D -E development
app 269 0.0 3.7 519760 152916 ? Sl 22:37 0:00 unicorn worker[0] -c config/unicorn.rb -D -E development
app 274 0.0 3.7 519760 152916 ? Sl 22:37 0:00 unicorn worker[1] -c config/unicorn.rb -D -E development
app 312 96.6 3.9 521744 161428 ? Rl 23:06 0:11 ruby /path/to/app/shared/bundle/ruby/2.2.0/bin/unicorn -c config/unicorn.rb -D -E development
app 337 0.0 0.0 8860 648 ? S+ 23:06 0:00 grep --color=auto unicorn
入れ替わり
新親が子プロセスを作る終わって、元の親がいなくなり、新親の親はinitになる。
$ pstree -anp; ps aux | grep unicorn
bash,1
|-sshd,35
|-nginx,44
| `-nginx,45
`-ruby,312
|-{ruby},329
|-{ruby},330
|-{ruby},334
|-ruby,338
| `-{ruby},340
|-ruby,343
| `-{ruby},345
`-{ruby},344
app 312 69.2 3.9 521748 161852 ? Sl 23:06 0:11 unicorn master -c config/unicorn.rb -D -E development
app 338 0.5 3.8 521748 154628 ? Sl 23:06 0:00 unicorn worker[0] -c config/unicorn.rb -D -E development
app 343 0.2 3.8 521748 154608 ? Sl 23:06 0:00 unicorn worker[1] -c config/unicorn.rb -D -E development
app 352 0.0 0.0 8860 648 ? S+ 23:06 0:00 grep --color=auto unicorn
USR2だと環境変数はよみ直さない
ということで、自分のコピーを作るだけなので環境変数は新しくしても読み込まないし、環境変数を消してもプロセスには残っている状態になっている。
仕方ないのでstop startする
対応
config/deploy.rbをこんな感じにしました。
今の環境だと、/path/to/secret/yml/env.ymlに環境変数に読み込むものを書いているので、そこのタイムスタンプが起動しているunicornのpidのタイムスタンプよりも新しかったら、unicornをstopして、unicorn_stop_sleep_time秒後にstartするように変更。
ついでに、rubyがバージョンアップした場合にもstop startするようにした。
namespace :deploy do
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# unix command execute status;
# 0 : true
# 1 : false
old_env = capture(
"/usr/bin/test /path/to/secret/yml/env.yml -ot #{fetch(:deploy_to)}/shared/tmp/pids/unicorn.pid; echo $?"
)
old_ruby = capture(
"/usr/bin/test /home/app/.rbenv/versions/#{fetch(:rbenv_ruby)} -ot #{fetch(:deploy_to)}/shared/tmp/pids/unicorn.pid; echo $?"
)
if old_env == '0' && old_ruby == '0'
info 'env.yml and ruby version is old. restat unicorn.'
invoke 'unicorn:restart'
else
info 'env.yml or ruby version is new. stop and start(reload env.yml) unicorn.'
invoke 'unicorn:stop'
execute :sleep, fetch(:unicorn_stop_sleep_time)
invoke 'unicorn:start'
end
end
end
after :publishing, :restart
end
まとめ
gitにcommitしたくないものをどうやって環境変数に持たせるか、から始まりunicornの再起動まで気を使う事になってきた。
実はもっといい方法がどこかにあるんじゃないかと思いつつもひとまずこれで運用する。