直径1.5メートル

ひよっこエンジニアのちょっとしたメモ。主に備忘録。

capistranoでデプロイしたときにunicornが再起動しない対応

capコマンドを使ってデプロイしたあと、unicornが再起動していないことが頻発します。

$ ps -ef | grep unicorn | grep -v grep
user  1234     1  0 19:08 ?        00:00:03 unicorn master -E staging -c <PRJ_ROOT>/current/config/unicorn/staging.rb -D
user  5678  1234  0 19:08 ?        00:00:00 unicorn worker[0] -E staging -c <PRJ_ROOT>/current/config/unicorn/staging.rb -D
user  9102  1234  0 19:08 ?        00:00:00 unicorn worker[1] -E staging -c <PRJ_ROOT>/current/config/unicorn/staging.rb -D

プロセスの起動時間がデプロイ時間より古ければ明らかにおかしいので、ひとまずログを確認。
すると、下記のようなログがあります。

I, [2016-06-06T16:01:57.399854 #26684]  INFO -- : forked child re-executing...
<HOME_DIRECTORY>/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/definition.rb:23:in `build': <PRJ_ROOT>/releases/20160603064119/Gemfile not found (Bundler::GemfileNotFound)

Bundler::GemfileNotFound なんて言われているけれど、確認するとちゃんとGemfileはあるのでオカシイ。
よく見ると、Gemfileを読み出そうとしている/releases以下のディレクトリ、この時点では既に過去のバージョンのものなので、ディレクトリ自体なかったりします。
なぜか古いGemfileを読み出そうとして、GemfileNotFoundを引き起こしている模様。

調べてみると、ENV['BUNDLE_GEMFILE']の値に古いGemfileのパスが入っていて、その値を利用してプロセスを起動するため「Gemfileないよ!」と言われているらしい。
対応として、before_execで明示的にパスを指定してあげれば、新しいGemfileを読みだすようになる。

# config/unicorn/staging.rb
current_dir = "<PRJ_ROOT>/current"
before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = File.expand_path('Gemfile', current_dir)
end

なんで起きるんだろう。

参考:
Capstarano3でデプロイ時にUnicornが再起動しているようで失敗している時の対処法 - Qiita