検索すると沢山でてきて、困らないのですが、
もっと運用しやすいようにログ出したり、エラーハンドリングしたり、作り込んでみました。

Unicornインストール

Gemfile に追加

# Use Unicorn
gem 'unicorn'
$ bundle install

Unicorn設定

デフォルトを定数で定義しつつ、環境変数があればそっちを優先するようにしました。
また、どの設定が使われているかも標準出力。unicorn_stdout.logにも出力されますね。
あと、エラーハンドリングも。

config/unicorn.rb を作成

unless defined?(DEFAULT_WORKER_PROCESSES)
  DEFAULT_WORKER_PROCESSES = 2
  DEFAULT_TIMEOUT = 60
  DEFAULT_LISTEN = File.expand_path('../tmp/sockets/unicorn.sock', __dir__).freeze
  DEFAULT_PID_PATH = File.expand_path('../tmp/pids/unicorn.pid', __dir__).freeze
  DEFAULT_STDERR_PATH = File.expand_path('../log/unicorn_stderr.log', __dir__).freeze
  DEFAULT_STDOUT_PATH = File.expand_path('../log/unicorn_stdout.log', __dir__).freeze
end
p "RAILS_ENV: #{ENV['RAILS_ENV'] || 'development(default)'}"
p "WORKER_PROCESSES: #{ENV['WORKER_PROCESSES'] || "#{DEFAULT_WORKER_PROCESSES}(default)"}"
p "TIMEOUT: #{ENV['TIMEOUT'] || "#{DEFAULT_TIMEOUT}(default)"}"
p "LISTEN: #{ENV['LISTEN'] || "#{DEFAULT_LISTEN}(default)"}"
pid_path = ENV['PID_PATH'] || DEFAULT_PID_PATH
p "PID_PATH: #{ENV['PID_PATH'] || "#{DEFAULT_PID_PATH}(default)"}[#{File.exist?(pid_path) ? File.read(pid_path).to_i : 'Not found'}]"
p "STDERR_PATH: #{ENV['STDERR_PATH'] || "#{DEFAULT_STDERR_PATH}(default)"}"
p "STDOUT_PATH: #{ENV['STDOUT_PATH'] || "#{DEFAULT_STDOUT_PATH}(default)"}"

worker_processes Integer(ENV['WORKER_PROCESSES'] || DEFAULT_WORKER_PROCESSES)
timeout Integer(ENV['TIMEOUT'] || DEFAULT_TIMEOUT)
preload_app true

listen ENV['LISTEN'] || DEFAULT_LISTEN
pid pid_path

stderr_path ENV['STDERR_PATH'] || DEFAULT_STDERR_PATH
stdout_path ENV['STDOUT_PATH'] || DEFAULT_STDOUT_PATH

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

  old_pid = "#{server.config[:pid]}.oldbin"
  if (old_pid != server.pid) && File.exist?(old_pid)
    begin
      signal = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(signal, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      p e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

タスク作成

作らなくても、コマンド打てばできますが、
タスク作って、エラーハンドリングもしておくと運用時に楽なので作成しました。

lib/tasks/unicorn.rake を作成

namespace :unicorn do
  DEFAULT_PID_PATH = File.expand_path('../../tmp/pids/unicorn.pid', __dir__).freeze

  desc 'Unicorn起動(bundle exec unicorn)'
  task(:start) do
    pid_path = ENV['PID_PATH'] || DEFAULT_PID_PATH
    if File.exist?(pid_path)
      p "Found: #{pid_path}"
      exit 1
    end

    rails_env = ENV['RAILS_ENV'] || 'development'
    sh "bundle exec unicorn -c config/unicorn.rb -D -E #{rails_env}"
  end

  desc 'Unicorn停止(QUIT)'
  task(:stop) { process_kill(:QUIT) }

  desc 'Unicorn再起動(HUP)'
  task(:restart) { process_kill(:HUP) }

  desc 'Unicorn緩やかな再起動(USR2)'
  task(:graceful) { process_kill(:USR2) }

  desc 'Unicornのワーカープロセスを増やす(TTIN)'
  task(:increment) { process_kill(:TTIN) }

  desc 'Unicornのワーカープロセスを減らす(TTOU)'
  task(:decrement) { process_kill(:TTOU) }

  desc 'Unicornプロセスの親子関係を確認(pstree)'
  task(:pstree) do
    pid_path = ENV['PID_PATH'] || DEFAULT_PID_PATH
    unless File.exist?(pid_path)
      p "Not found: #{pid_path}"
      exit 1
    end

    sh "pstree `cat #{pid_path}`"
  end

  # killシグナルを送る
  def process_kill(signal)
    pid_path = ENV['PID_PATH'] || DEFAULT_PID_PATH
    unless File.exist?(pid_path)
      p "Not found: #{pid_path}"
      exit 1
    end

    sh "kill -#{signal} `cat #{pid_path}`"
  end
end

使い方

タスク一覧出すだけで、コマンドと内容が分かります。
やはり日本語だと分かりやすいですね。

$ rails -T
rails unicorn:decrement                  # Unicornのワーカープロセスを減らす(TTOU)
rails unicorn:graceful                   # Unicorn緩やかな再起動(USR2)
rails unicorn:increment                  # Unicornのワーカープロセスを増やす(TTIN)
rails unicorn:pstree                     # Unicornプロセスの親子関係を確認(pstree)
rails unicorn:restart                    # Unicorn再起動(HUP)
rails unicorn:start                      # Unicorn起動(bundle exec unicorn)
rails unicorn:stop                       # Unicorn停止(QUIT)

【参考】ここまでのコミット内容
https://dev.azure.com/nightonly/rails-app-origin/_git/rails-app-origin/commit/c7d9cf570ce15d33d31094dae65c91cdb800983d

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です