capistrano-unicornでハマった

capistrano-unicornはその名の通りcapistranounicornを扱う便利なgemです。
早速Railsのサービスに導入してみた。

試した環境は

githubの使い方を参考にGemfileに下記を追加してbundle叩く

group :development do
  gem 'capistrano-unicorn', :require => false
end

config/deploy.rbでrequireするのとdeploy:restart時のcollbackを登録

# set :application宣言より下に書かないとエラーになる
require 'capistrano-unicorn'

...

# hot deployを利用するため unicorn:restartを指定
after 'deploy:restart', 'unicorn:restart' 

unicorn設定ファイル(config/unicorn.rb)を作成

# Set your full path to application.
app_path = "/var/www/vhosts/blog/current"

# Set unicorn options
worker_processes 3
preload_app true
timeout 30
listen "/tmp/unicorn.blog.sock"

# Spawn unicorn master worker for user apps (group: apps)
user 'rubys', 'rubys'

# Fill path to your app
working_directory app_path

# Should be 'production' by default, otherwise use other env 
rails_env = ENV['RAILS_ENV'] || 'production'

# Log everything to one file
stderr_path "log/unicorn.log"
stdout_path "log/unicorn.log"

# Set master PID location
pid "#{app_path}/tmp/pids/unicorn.pid"

before_fork do |server, worker|
  ActiveRecord::Base.connection.disconnect!

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
  ActiveRecord::Base.establish_connection
end

ここまでで準備はOKのようです、追加、変更したファイルはこんな感じで配置されます。

Gemfile
config
|-- deploy.rb
|-- unicorn.rb

準備も整ったのでcap deployしてみると..

  * 2012-12-22 02:19:17 executing `deploy:restart'
    triggering after callbacks for `deploy:restart'
  * 2012-12-22 02:19:17 executing `unicorn:reload'
  * executing "if [ -e /var/www/vhosts/realplay/current/tmp/pids/unicorn.pid ]; then echo 'true'; fi"
    servers: ["192.168.6.29"]
    [192.168.6.29] executing command
    command finished in 3739ms
*** [Unicorn] Stopping...
  * executing "kill -s USR2 `cat /var/www/vhosts/realplay/current/tmp/pids/unicorn.pid`"
    servers: ["192.168.6.29"]
    [192.168.6.29] executing command
    command finished in 3646ms
the task `unicorn:restart' does not exist

あれ、after 'deploy:restart', 'unicorn:restart'を呼んでるのにunicorn:reloadが呼ばれてる。
しかもunicorn:restartがないとも言ってるし。

github上のソースコード見る限りちゃんとrestart定義されてるし..

task :restart, :roles => :app, :except => {:no_release => true} do
  run <<-END
    if #{unicorn_is_running?}; then
      echo "Restarting Unicorn...";
      #{unicorn_send_signal('USR2')};
    else
      #{start_unicorn}
    fi;

    sleep 2; # in order to wait for the (old) pidfile to show up

    if #{old_unicorn_is_running?}; then
      #{unicorn_send_signal('QUIT', get_old_unicorn_pid)};
    fi;
  END
end

githubのmasterのversion.rbも0.1.6になってるし古いバージョンを入れているわけではなさそう。
しかたなくインストールされているソースを見るとなんとunicorn:restartが定義されていない。
どうもrubygems.orgに上がっているソースは最新ではないようなのでgithubからインストールするように変更する。

group :development do
  gem 'capistrano-unicorn', :git => 'git@github.com:sosedoff/capistrano-unicorn.git'
end

再度deployしてみる。

  * 2012-12-22 04:25:11 executing `deploy:restart'    triggering after callbacks for `deploy:restart'
  * 2012-12-22 04:25:11 executing `unicorn:restart'
    triggering before callbacks for `unicorn:restart'
...
    [192.168.6.29] executing command
 ** [out :: 192.168.6.29] Restarting Unicorn...

想定どおり、unicorn:restartが動いてくれた。