Skip to content

Instantly share code, notes, and snippets.

@joakimk
Created February 7, 2013 12:57
Show Gist options
  • Save joakimk/4730744 to your computer and use it in GitHub Desktop.
Save joakimk/4730744 to your computer and use it in GitHub Desktop.
Using unicorn with preload_app. Init script, unicorn config and base environment. (not used in production yet). ERB templates.
#!/bin/sh
UNICORN_CONF="/data/<%= @app_name %>/shared/config/unicorn.rb"
UNICORN_EXEC="bundle exec unicorn"
UNICORN_PID="/var/run/<%= @app_name %>/unicorn.pid"
UNICORN_MAX_RELOAD_WAIT_TIME=60000 # 60 seconds
RAILS_ENV="<%= @rails_env %>"; export RAILS_ENV
RACK_ENV="<%= @rails_env %>"; export RACK_ENV
APP_ROOT=/data/<%= @app_name %>/current
# Monit scrubs the environment; which makes Unicorn behave badly sometimes.
export USER="<%= @user %>"
export HOME="/home/$USER"
export LANG=en_US.utf8
export SHELL="/bin/bash"
# When using preload_app, you need to restart using USR2 and kill
# the old master yourself.
preload_app true
before_fork do |server, worker|
old_pid = "#{server.config[:pid]}.oldbin"
##
# When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
# immediately start loading up a new version of itself (loaded with a new
# version of our app). When this new Unicorn is completely loaded
# it will begin spawning workers. The first worker spawned will check to
# see if an .oldbin pidfile exists. If so, this means we've just booted up
# a new Unicorn and need to tell the old one that it can now die. To do so
# we send it a QUIT.
if File.exists?(old_pid) && server.pid != old_pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :TERM : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
sleep 1
end
#!/bin/bash
#
# init.d script for unicorn.
set -e
source /data/<%= @app_name %>/shared/env/base
signal () {
test -s "$UNICORN_PID" && kill -$1 `cat "$UNICORN_PID"`
}
old_master_is_alive() {
(kill -0 $old_master_pid 2> /dev/null) && return 0 || return 1
}
run () {
cd $APP_ROOT || exit 1
CMD="$UNICORN_EXEC -E $RACK_ENV -c $UNICORN_CONF -D $APP_ROOT/config.ru"
case $1 in
start)
signal 0 && echo >&2 "Already running" && exit 0
printf "Starting... "
$CMD
echo "done"
;;
stop)
printf "Stopping... "
signal QUIT && echo "done" && exit 0
echo >&2 "Not running"
;;
force-stop)
printf "Force-stopping... "
signal TERM && echo "done" && exit 0
echo >&2 "Not running"
;;
restart)
# Normally when you send USR2 you must also ensure you kill the old master. We
# have a hook in unicorn.rb that does this for us.
old_master_pid=$(cat $UNICORN_PID)
printf "Restarting" && signal USR2
while old_master_is_alive; do
printf "."
sleep 0.1
let "wait_for_new_master_time += 100"
if (($wait_for_new_master_time >= $UNICORN_MAX_RELOAD_WAIT_TIME)); then
echo
echo
echo "Restart failed: It took longer than $(($UNICORN_MAX_RELOAD_WAIT_TIME / 100)) seconds for the old master to stop."
echo
exit 1
fi
done
echo " done"
;;
*)
echo >&2 "Usage: $0 <start|stop|force-stop|restart>"
exit 1
;;
esac
}
run $1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment