Created
September 16, 2011 10:12
-
-
Save shapeshed/1221753 to your computer and use it in GitHub Desktop.
Unicorn / Monit setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -e | |
# Example init script, this can be used with nginx, too, | |
# since nginx and unicorn accept the same signals | |
# Feel free to change any of the following variables for your app: | |
TIMEOUT=${TIMEOUT-60} | |
APP_ROOT=/path/to/your/app/current | |
PID=$APP_ROOT/tmp/pids/unicorn.pid | |
ENVIRONMENT=production | |
CMD="cd $APP_ROOT; bundle exec unicorn -E $ENVIRONMENT -D -c $APP_ROOT/config/unicorn.rb" | |
action="$1" | |
set -u | |
old_pid="$PID.oldbin" | |
cd $APP_ROOT || exit 1 | |
sig () { | |
test -s "$PID" && kill -$1 `cat $PID` | |
} | |
oldsig () { | |
test -s $old_pid && kill -$1 `cat $old_pid` | |
} | |
workersig () { | |
workerpid="$APP_ROOT/tmp/pids/unicorn.$2.pid" | |
test -s "$workerpid" && kill -$1 `cat $workerpid` | |
} | |
case $action in | |
m start) | |
sig 0 && echo >&2 "Already running" && exit 0 | |
su - rails -c "$CMD" | |
;; | |
stop) | |
sig QUIT && exit 0 | |
echo >&2 "Not running" | |
;; | |
force-stop) | |
sig TERM && exit 0 | |
echo >&2 "Not running" | |
;; | |
restart|reload) | |
sig HUP && echo reloaded OK && exit 0 | |
echo >&2 "Couldn't reload, starting '$CMD' instead" | |
su - rails -c "$CMD" | |
;; | |
upgrade) | |
if sig USR2 && sleep 20 && sig 0 && oldsig QUIT | |
then | |
n=$TIMEOUT | |
while test -s $old_pid && test $n -ge 0 | |
do | |
printf '.' && sleep 1 && n=$(( $n - 1 )) | |
done | |
echo | |
if test $n -lt 0 && test -s $old_pid | |
then | |
echo >&2 "$old_pid still exists after $TIMEOUT seconds" | |
exit 1 | |
fi | |
exit 0 | |
fi | |
echo >&2 "Couldn't upgrade, starting '$CMD' instead" | |
su - rails -c "$CMD" | |
;; | |
kill_worker) | |
workersig QUIT $2 && exit 0 | |
echo >&2 "Worker not running" | |
;; | |
reopen-logs) | |
sig USR1 | |
;; | |
*) | |
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>" | |
exit 1 | |
;; | |
esac |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
APP_ROOT = File.expand_path(File.dirname(File.dirname(__FILE__))) | |
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm') | |
begin | |
rvm_path = File.dirname(File.dirname(ENV['MY_RUBY_HOME'])) | |
rvm_lib_path = File.join(rvm_path, 'lib') | |
$LOAD_PATH.unshift rvm_lib_path | |
require 'rvm' | |
RVM.use_from_path! APP_ROOT | |
rescue LoadError | |
raise "RVM ruby lib is currently unavailable." | |
end | |
end | |
ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__)) | |
require 'bundler/setup' | |
worker_processes 1 | |
working_directory APP_ROOT | |
preload_app true | |
timeout 30 | |
listen APP_ROOT + "/tmp/sockets/unicorn.sock", :backlog => 64 | |
pid APP_ROOT + "/tmp/pids/unicorn.pid" | |
stderr_path APP_ROOT + "/log/unicorn.stderr.log" | |
stdout_path APP_ROOT + "/log/unicorn.stdout.log" | |
before_fork do |server, worker| | |
defined?(ActiveRecord::Base) && ActiveRecord::Base.connection.disconnect! | |
old_pid = Rails.root + '/tmp/pids/unicorn.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 | |
puts "Old master alerady dead" | |
end | |
end | |
end | |
after_fork do |server, worker| | |
defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection | |
child_pid = server.config[:pid].sub('.pid', ".#{worker.nr}.pid") | |
system("echo #{Process.pid} > #{child_pid}") | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
check process unicorn_worker_0 | |
with pidfile /path/to/your/app/shared/pids/unicorn.0.pid | |
start program = "/bin/cat /dev/null" | |
stop program = "/etc/init.d/unicorn kill_worker 0" | |
if mem is greater than 175.0 MB for 1 cycles then restart | |
if cpu is greater than 22% for 2 cycles then alert | |
if cpu is greater than 25% for 1 cycles then restart |
This line has a typo (remove extra "m")
https://gist.github.com/shapeshed/1221753#file-unicorn-L33
Should look like:
case $action in
start)
Guys, there is little problem with using unicorn service under «rails» user. It requires root password because of su - rails -c "$CMD"
.
In my script I:
- defined additional two vars
APP_USER="deployer"
CURRENT_USER=`whoami`
- new function
exec_unicorn_cmd () {
if [ "$CURRENT_USER" = $APP_USER ]
then
eval $CMD
else
su - $APP_USER -c "$CMD"
fi
}
- and using
exec_unicorn_cmd
insteadsu - rails -c "$CMD"
(lines 35, 48, 68).
And it's works fine for all users. ;o)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just a note, I've been running into something of a race condition on killing the old master with a similar setup.
Both the unicorn init script and the unicorn app script attempt to kill the old master. If the app kills it before the init script, then the init script
upgrade
will fail.I figure it's better to just let the app kill off the old master since that guarantees that the new master is running the app.
The upgrade action can simply be: