Here's what I've set up in order to try ensure that Mongrel is running. (This setup tries to deal with the dreaded 503 Service Temporarily Unavailable error). The watcher should monitor the Mongrel, and try to make sure the site is running.
Every few seconds it checks whether Mongrel is running.
If there would be a problem that would cause Mongrel to crash each time shortly after it has been started, then a monitoring tool might (try to) start Mongrel many hundred times per hour.
So if my watcher finds no running Mongrel, it will try to start one, but then it will send a notification email and sleep for an hour.
The setup works for me, with one Mongrel running one site in one account.
Here are the files:
script/at_reboot:
# In the crontab I have (from crontab -l):
# @reboot cd skatestuff_freebox/current && script/at_reboot
export PATH=/usr/local/bin:/usr/bin:/bin
mongrel_port=4076
sleep 10
rm -f tmp/pids/dispatch.${mongrel_port}.pid
script/spin $mongrel_port
sleep 5
script/start_watcher $mongrel_port
script/request_loop
script/spin:
mongrel_port=$1 command="pgrep -u skatest -f 'mongrel_rails start.+-p $mongrel_port'" if [ -z "$(echo $command | sh -s)" ]; then nohup ruby script/process/spawner mongrel -e production -p $mongrel_port -i 1 fiscript/start_watcher:
mongrel_port=$1 command="pgrep -u skatest -f 'script/watcher.+$mongrel_port'" if [ -z "$(echo $command | sh -s)" ]; then nohup script/watcher $mongrel_port & fiscript/watcher:
mongrel_port=$1
function get_mongrel_line {
command="pgrep -u skatest -l -f 'mongrel_rails start.+-p $mongrel_port'"
echo "$(echo $command | sh -s)"
}
function react_to_no_mongrel_running {
alert="It seems there's no Mongrel running.\n"
rm -f tmp/pids/dispatch.${mongrel_port}.pid
script/spin $mongrel_port
alert="$alert\nI tried to start one.\n"
sleep 5
mongrel_line=$(get_mongrel_line)
if [ -z "$mongrel_line" ]; then
alert="$alert\nIt seems there still is no Mongrel running.\n"
else
alert="$alert\nIt seems that now there is a Mongrel running:"
alert="$alert\n$mongrel_line\n"
fi
alert="$alert\nPerhaps the app needs to be fixed?\n"
alert="$alert\nI'm gonna sleep for one hour.\n"
alert="$alert\nHere are the last lines of the production and mongrel logs:\n"
alert="$alert\n$(tail -n 150 log/production.log)\n\n"
alert="$alert\n$(tail -n 150 log/mongrel.log)\n"
echo -e "$alert" | \
mail -s "Watcher alert from skatestuff-freebox.org" \
"$(tee < config/email_address)"
sleep 1h
}
while [ 1 = 1 ]; do
mongrel_line=$(get_mongrel_line)
if [ -z "$mongrel_line" ]; then
# It seems there's no Mongrel running, so
react_to_no_mongrel_running
fi
sleep 2
done
Capfile:
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
load 'config/deploy'
after "deploy:update_code", "deploy:fix_script_perms"
after "deploy:update_code", "deploy:set_up_database_yml"
after "deploy:update_code", "deploy:set_env"
after "deploy:update_code", "deploy:link_rails"
# Sometimes this will be redundant:
before "deploy:stop", "deploy:stop_watcher"
# Works around a strange missing PID file issue, IIRC:
before "deploy:update_code", "deploy:stop_watcher"
# before "deploy:update_code", "deploy:stop_request_loop"
# after "deploy:stop", "deploy:mongrel_status"
before "deploy:stop", "deploy:stop_request_loop"
# after "deploy:stop_watcher", "deploy:watcher_status"
# after "deploy:start_watcher", "deploy:watcher_status"
after "deploy:start", "deploy:start_watcher"
# after "deploy:start", "deploy:mongrel_status"
after "deploy:start", "deploy:start_request_loop"
# before "deploy:restart", "deploy:stop_watcher"
# after "deploy:restart", "deploy:start_watcher"
# after "deploy:restart", "deploy:mongrel_status"
set :migrate_target, :latest
# before "deploy:symlink", "deploy:migrate"
after "deploy", "deploy:cleanup"
namespace :deploy do
task :fix_script_perms do
run "cd #{latest_release} && chmod 755 #{chmod755}"
end
task :set_up_database_yml do
run "mv #{latest_release}/config/database.yml.online " +
"#{latest_release}/config/database.yml"
end
task :set_env do
run "(echo '/RAILS_ENV/s/^# //'; echo 'wq') | " +
"ed -s #{latest_release}/config/environment.rb"
end
task :link_rails do
run "ln -s ~/rails/current #{latest_release}/vendor/rails"
end
task :stop do
run "cd #{current_path} && script/process/reaper -a graceful; sleep 2"
end
# Just a hack
task :restart do
deploy.stop
# Works OK here?
deploy.migrate
deploy.start
end
task :start do
run "cd #{current_path} && script/spin #{mongrel_port}"
end
task :start_watcher do
# sleep 5 &&
run "cd #{current_path} && nohup script/start_watcher #{mongrel_port}"
end
task :stop_watcher do
run "pkill -u #{user} -f 'script/watcher #{mongrel_port}'"
end
task :start_request_loop do
run "cd #{current_path} && nohup script/start_request_loop"
end
task :stop_request_loop do
run "pkill -u #{user} -f 'script/request_loop'"
end
task :mongrel_status do
run "echo 'Mongrel:'; " +
" echo \"$(pgrep -u #{user} -l -f 'mongrel_rails start'" +
" | grep -v 'pgrep')\""
end
task :watcher_status do
run "echo 'Watcher:';" +
" echo \"$(pgrep -u #{user} -l -f 'script/watcher'" +
" | grep -v 'pgrep')\""
end
task :my_cleanup do
run "cd #{latest_release} && rm -f nohup.out log/*"
end
end