[rails]unicorn設定ファイルと起動スクリプトのメモ


unicorn設定は毎回同じことを書いている気がするのでメモしておきます。

ついでに起動スクリプトを作って自動起動する設定もメモしておきます。

unicorn設定

1. Gemfileに追加

gem 'unicorn'

2. unicorn.rbを追加

# config/unicorn.yml

require "yaml"
RAILS_ROOT   = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
RAILS_ENV    = ENV['RAILS_ENV'] || 'development'
CONFIG       = YAML.load_file(RAILS_ROOT + "/config/unicorn.yml")[RAILS_ENV]

worker_processes CONFIG["worker_processes"]
preload_app true
timeout 60
listen CONFIG["listen"], :backlog => 1024

pid "#{RAILS_ROOT}/tmp/pids/unicorn.pid"

stderr_path "#{RAILS_ROOT}/log/unicorn.log"
stdout_path "#{RAILS_ROOT}/log/unicorn.log"

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{ server.config[:pid] }.oldbin"
  unless old_pid == server.pid
    begin
      Process.kill :QUIT, File.read(old_pid).to_i
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = "#{RAILS_ROOT}/Gemfile"
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

3. 環境に応じて設定を変更できるようunicorn.ymlを追加

# config/unicorn.yml

development:
  worker_processes: 1
  listen: "unix:/home/app/sample/development/current/tmp/sockets/unicorn.sock"

staging:
  worker_processes: 2
  listen: "unix:/home/app/sample/staging/current/tmp/sockets/unicorn.sock"

production:
  worker_processes: 16
  listen: "unix:/home/app/sample/production/current/tmp/sockets/unicorn.sock"

4. アプリケーション起動

上記の設定を行った状態で

bundle exec unicorn_rails -c /home/app/sample/development/current/config/unicorn.rb -E development -D

を実行すればdevelopmentモード(-Eオプション)、デーモン状態(-Dオプション)でunicornが起動します。

自動起動設定

OSはCentOS6.5で確認

1. 起動スクリプトの作成

今回はアプリケーションのルートディレクトリ以下に起動スクリプトを作成します。

appユーザで起動する想定です。

{RAILS_ROOT}/unicorn_sample として以下を保存します。

#!/bin/sh
# chkconfig: 345 90 20
# description: Rails application sample
# processname: unicorn_sample

RAILS_ENV=production
SERVICE=sample_production
USER=app

RAILS_ROOT_DIR="/home/app/sample/production/current"

PID=${RAILS_ROOT_DIR}/tmp/pids/unicorn.pid
UNICORN_CONF=${RAILS_ROOT_DIR}/config/unicorn.rb

UNICORN_ALIVE=`ps aux|grep '${UNICORN_CONF}'|grep -v grep|wc -l`

start()
{
  if [ $UNICORN_ALIVE = 0 ]; then
    rm -f $PID
  fi
  if [ -e ${PID} ]; then
    echo "${SERVICE} already started"
    exit 1
  fi
  echo "start ${SERVICE}"
  sudo su -l ${USER} -c "source /etc/environment && cd ${RAILS_ROOT_DIR} && bin/unicorn_rails -c ${UNICORN_CONF} -E ${RAILS_ENV} -D"
}

stop()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    exit 1
  fi
  echo "stop ${SERVICE}"
  kill -QUIT `cat ${PID}`
}

force_stop()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    exit 1
  fi
  echo "stop ${SERVICE}"
  kill -INT `cat ${PID}`
}

reload()
{
  if [ ! -e ${PID} ]; then
    echo "${SERVICE} not started"
    start
    exit 0
  fi
  echo "reload ${SERVICE}"
  kill -USR2 `cat ${PID}`
}

restart()
{
  if [ -e ${PID} ]; then
    stop
    sleep 3
  fi
  start
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  force-stop)
    force_stop
    ;;
  reload)
    reload
    ;;
  restart)
    restart
    ;;
  *)
    echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
    ;;
esac

2. /etc/init.d以下にシンボリックリンク追加

sudo ln -s /home/app/sample/production/current/unicorn_sample /etc/init.d/

3. 自動起動設定追加

自動起動をonにします。

sudo chkconfig unicorn_sample on

確認

sudo chkconfig --list | grep unicorn_sample

#####
unicorn_sample       0:off   1:on    2:on    3:on    4:on    5:on    6:off

これでunicornの自動起動が有効になりました。

起動スクリプトはchefのレシピにしておくと使い回しがききそうですね。