Skip to content

Instantly share code, notes, and snippets.

@danman01
Last active January 4, 2016 15:29
Show Gist options
  • Save danman01/8640750 to your computer and use it in GitHub Desktop.
Save danman01/8640750 to your computer and use it in GitHub Desktop.
Avoid already running / unable to listen errors while using capistrano-unicorn with monit / God / upstart scripts

Make sure that your init.d or upstart scripts to manage Unicorn and its workers are taken into account when capistrano-unicorn is doing the unicorn restart / reload / duplication tasks.

I did not think to look at these scripts when I had to debug the stale pid file / already running / unable to listen on socket errors. But it makes sense, as upstart starts Unicorn when it is not running, and then capistrano-unicorn is also attempting to start Unicorn.

I combine these capistrano tasks and hooks with Monit and a Unicorn init script.

Capistrano tasks:

namespace :monit do
  desc ' wait 20 seconds '
  task :wait_20_seconds do
    sleep 20
  end
  task :monitor_all, :roles => :app do
    sudo "monit monitor all"
  end

  task :unmonitor_all, :roles => :app do
    sudo "monit unmonitor all"
  end
  
  desc 'monitor unicorn in the monit rc file'
  task :monitor_unicorn, :roles => :app do
    sudo "monit monitor unicorn"
  end

  desc 'unmonitor unicorn in the monit rc file'
  task :unmonitor_unicorn, :roles => :app do
    sudo "monit unmonitor unicorn"
  end
end

Capistrano hooks:

after 'deploy:restart', 'unicorn:duplicate'  # app preloaded. check https://github.com/sosedoff/capistrano-unicorn section for zero downtime

before 'deploy', "monit:unmonitor_unicorn"
before 'deploy:migrations', "monit:unmonitor_unicorn"

after 'deploy', 'monit:wait_20_seconds'
after "deploy:migrations", "monit:wait_20_seconds"

after 'monit:wait_20_seconds', 'monit:monitor_unicorn'

I use Monit to monitor my unicorn process:

Within /etc/monit/monitrc:

check process unicorn
  with pidfile /var/www/apps/my_app/shared/pids/mypid.pid
  start program = "/usr/bin/sudo service unicorn start"
  stop program = "/usr/bin/sudo service unicorn stop"

Sudo service unicorn points to an init script located within init.d (and has been converted to use upstarts' service serviceName command syntax)

My init script:

#! /bin/bash

### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the unicorn web server
# Description:       starts unicorn
### END INIT INFO

# note that these options, specifically daemon_opts and daemon should mesh with the options you supply in deploy.rb
USER=your_user
PATH=your_$PATH
DAEMON=unicorn_rails
DAEMON_OPTS=your_daemon_opts
#example daemon: "-c /var/www/apps/my_app/current/config/unicorn.rb -E staging -D"
NAME=unicorn
DESC="Unicorn app for $USER"
PID=your_pid_location
APP_ROOT=your_app_root

# look at http://unicorn.bogomips.org/examples/init.sh for inspiration and updated init script

old_pid="$PID.oldbin"

cd $APP_ROOT || exit 1


case "$1" in
  start)
        CD_TO_APP_DIR="cd $APP_ROOT"
        START_DAEMON_PROCESS="bundle exec $DAEMON $DAEMON_OPTS"

        echo -n "Starting $DESC: "
        if [ `whoami` = root ]; then
          su - $USER -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS"
        else
          $CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS
        fi
        echo "finished starting $NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        kill -QUIT `cat $PID`
        echo "$NAME."
        ;;
  restart)
        echo -n "Restarting $DESC: "
        kill -USR2 `cat $PID`
        echo "$NAME."
        ;;
  reload)
        echo -n "Reloading $DESC configuration: "
        kill -HUP `cat $PID`
        echo "$NAME."
        ;;
  *)
        echo "Usage: $NAME {start|stop|restart|reload}" >&2
        exit 1
        ;;
esac

exit 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment