Skip to content

Instantly share code, notes, and snippets.

@jurikern
Last active August 29, 2015 14:07
Show Gist options
  • Save jurikern/5f9c8fbb41da6e2ee977 to your computer and use it in GitHub Desktop.
Save jurikern/5f9c8fbb41da6e2ee977 to your computer and use it in GitHub Desktop.
Unicorn task for zero downtime deployment
namespace :load do
task :defaults do
set :pids_dir, -> { File.join(current_path, 'tmp', 'pids') }
set :unicorn_pid, -> { File.join(fetch(:pids_dir), "unicorn.pid") }
set :unicorn_config_path, -> { File.join(current_path, "config", "unicorn", "#{fetch(:rails_env)}.rb") }
set :unicorn_roles, -> { :app }
set :unicorn_options, -> { "" }
set :unicorn_rack_env, -> { fetch(:rails_env) == "development" ? "development" : "deployment" }
set :unicorn_restart_sleep_time, 3
end
end
namespace :unicorn do
desc "Start Unicorn"
task :start do
on roles(fetch(:unicorn_roles)) do
within current_path do
if test("[ -e #{fetch(:unicorn_pid)} ] && kill -0 #{pid}")
info "unicorn is running..."
else
with rails_env: fetch(:rails_env) do
cmd = <<-EOS
bundle exec unicorn
-c #{fetch(:unicorn_config_path)}
-E #{fetch(:unicorn_rack_env)}
-D #{fetch(:unicorn_options)}
EOS
begin RuntimeError
execute cmd
rescue
execute "if [[ ! -e #{fetch(:pids_dir)} ]]; then mkdir -p #{fetch(:pids_dir)}; fi"
execute "ps aux | grep 'unicorn master' | awk '{print $2}' | xargs sudo kill -9"
execute cmd
end
end
end
end
end
end
desc "Stop Unicorn (QUIT)"
task :stop do
on roles(fetch(:unicorn_roles)) do
within current_path do
if test("[ -e #{fetch(:unicorn_pid)} ]")
if test("kill -0 #{pid}")
info "stopping unicorn..."
execute :kill, "-s QUIT", pid
else
info "cleaning up dead unicorn pid..."
execute :rm, fetch(:unicorn_pid)
end
else
info "unicorn is not running..."
end
end
end
end
desc "Reload Unicorn (HUP); use this when preload_app: false"
task :reload do
invoke "unicorn:start"
on roles(fetch(:unicorn_roles)) do
within current_path do
info "reloading..."
execute :kill, "-s HUP", pid
end
end
end
desc "Restart Unicorn (USR2); use this when preload_app: true"
task :restart do
invoke "unicorn:start"
on roles(fetch(:unicorn_roles)) do
within current_path do
info "unicorn restarting..."
execute :kill, "-s USR2", pid
end
end
end
desc "Duplicate Unicorn; alias of unicorn:restart"
task :duplicate do
invoke "unicorn:restart"
end
desc "Legacy Restart (USR2 + QUIT); use this when preload_app: true and oldbin pid needs cleanup"
task :legacy_restart do
invoke "unicorn:restart"
on roles(fetch(:unicorn_roles)) do
within current_path do
execute :sleep, fetch(:unicorn_restart_sleep_time)
if test("[ -e #{fetch(:unicorn_pid)}.oldbin ]")
execute :kill, "-s QUIT", pid_oldbin
end
end
end
end
desc "Add a worker (TTIN)"
task :add_worker do
on roles(fetch(:unicorn_roles)) do
within current_path do
info "adding worker"
execute :kill, "-s TTIN", pid
end
end
end
desc "Remove a worker (TTOU)"
task :remove_worker do
on roles(fetch(:unicorn_roles)) do
within current_path do
info "removing worker"
execute :kill, "-s TTOU", pid
end
end
end
end
def pid
"`cat #{fetch(:unicorn_pid)}`"
end
def pid_oldbin
"`cat #{fetch(:unicorn_pid)}.oldbin`"
end
# config.ru Based an 2 workers for 1GB RAM, 1-core system
if defined?(Unicorn)
require "unicorn/worker_killer"
use Unicorn::WorkerKiller::Oom, (350*(1024**2)), (400*(1024**2))
end
# startup options
crontab -e
@reboot /bin/bash -l -c "cd /app_path/current && ( RAILS_ENV=production bundle exec unicorn -c /app_path/current/config/unicorn/production.rb -E deployment -D )"
# Results:
# 101msec/request average rate, 10000 requests in minute, 0% errors rate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment