Skip to content

Instantly share code, notes, and snippets.

@tjl2
Created January 29, 2012 09:49
Show Gist options
  • Save tjl2/1698074 to your computer and use it in GitHub Desktop.
Save tjl2/1698074 to your computer and use it in GitHub Desktop.
#!/bin/sh
#
# This script starts and stops the Dj daemon
# This script belongs in /engineyard/bin/dj
#
PATH=/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
CURDIR=`pwd`
usage() {
echo "Usage: $0 <appname> {start|stop} enviroment [name maximum_priority minimum_priority]"
exit 1
}
if [ $# -lt 3 ]; then usage; fi
if [ $4 ]; then
NAME="_$4"
if [ $5 ]; then
OPTIONS=":max_priority=>$5"
if [ $6 ]; then
OPTIONS="$OPTIONS,:min_priority=>$6"
fi
OPTIONS="{$OPTIONS}"
fi
fi
if [ "`whoami`" != "root" ]; then
logger -t `basename $0` -s "Must be run as root"
exit 1
fi
## Function definitions - casual readers encouraged to skip this ##
rm_lockfile(){
if [ -e $LOCK_FILE ]; then
logger -t "monit_dj:$WORKER[$$]" "removing $LOCK_FILE for `cat $LOCK_FILE`"
rm $LOCK_FILE
fi
}
lock(){
RESULT=0
if [ -e $LOCK_FILE ]; then
LAST_LOCK_PID=`cat $LOCK_FILE`
if [ -n $LAST_LOCK_PID -a -z "`ps axo pid|grep $LAST_LOCK_PID`" -a -f $LOCK_FILE ];then
sleep 1
logger -t "monit-dj:$WORKER[$$]" "Removing stale lock file for $WORKER ($LAST_LOCK_PID)"
rm $LOCK_FILE 2>&1
else
logger -t "monit-dj:$WORKER[$$]" "Monit already messing with $WORKER ($LAST_LOCK_PID)"
RESULT=1
exit_cleanly
fi
fi
echo $$ > $LOCK_FILE
}
exit_cleanly() {
cd $CURDIR
logger -t "mont-dj:$WORKER[$$]" "exiting wrapper cleanly with $RESULT"
exit $RESULT
}
unlock_and_exit_cleanly(){
rm_lockfile
exit_cleanly
}
## End function definitions ##
#set -x
WORKER=$1$NAME
LOCK_FILE="/tmp/$WORKER.monit-lock"
BUNDLER_COMMAND="ruby"
RAILS_ROOT=/data/$1/current
if [ -d $RAILS_ROOT ]; then
if [ -f $RAILS_ROOT/Gemfile ]; then
if [ -d $RAILS_ROOT/ey_bundler_binstubs ]; then
PATH=$RAILS_ROOT/ey_bundler_binstubs:$PATH
else
BUNDLER_COMMAND="bundle exec ruby"
fi
fi
RAILS_ENV=$3
export $RAILS_ENV
RUNNER='runner'
#RAILS_SCRIPTS="$RAILS_ROOT/script"
RAILS_SCRIPTS="$RAILS_ROOT/script"
[ -f $RAILS_SCRIPTS/rails ] && chmod a+x $RAILS_SCRIPTS/rails && RUNNER="rails runner"
cd $RAILS_ROOT
PID_FILE=/var/run/engineyard/dj/$1/dj$NAME.pid
USER=`stat -c"%U" /data/$1/current/`
HOME="/home/$USER" ; export HOME
RESULT=0
GRACE_TIME=${GRACE_TIME:-60}
let "GRACE_TIME=$GRACE_TIME*4"
mkdir -p /var/run/engineyard/dj/$1
case "$2" in
start)
lock
cd $RAILS_ROOT
HAS_DJ_COMMAND="RAILS_ENV=$RAILS_ENV $BUNDLER_COMMAND $RAILS_SCRIPTS/$RUNNER -e $RAILS_ENV \"require 'delayed/command';puts defined?(Delayed::Command)\" 2>/dev/null"
has_dj_command=$(sudo -u $USER -H /bin/bash -c "$HAS_DJ_COMMAND")
if [[ $has_dj_command == "constant" ]];then
OPTIONS=${OPTIONS:-[]}
HAS_BEFORE_FORK="RAILS_ENV=$RAILS_ENV $BUNDLER_COMMAND $RAILS_SCRIPTS/$RUNNER -e $RAILS_ENV \"require 'delayed/worker';puts Delayed::Worker.respond_to?(:before_fork)\" 2>/dev/null"
has_before_fork=$(sudo -u $USER -H /bin/bash -c "$HAS_BEFORE_FORK")
if [[ $has_before_fork == "true" ]];then
RUNNER_COMMAND="require 'delayed/command';Delayed::Worker.before_fork;Delayed::Command.new($OPTIONS).run"
else
RUNNER_COMMAND="require 'delayed/command';Delayed::Command.new($OPTIONS).run"
fi
else
RUNNER_COMMAND="Delayed::Worker.new($OPTIONS).start"
fi
COMMAND="$BUNDLER_COMMAND $RAILS_SCRIPTS/$RUNNER -e $RAILS_ENV \"$RUNNER_COMMAND\""
logger -t "monit-dj:$WORKER[$$]" "DJ Worker starting from $PPID"
if [ -f $PID_FILE ]; then
PID=`cat $PID_FILE`
if [ -n "$PID" ];then
logger -t "monit-dj:$WORKER[$$]" "There is already a PID file for delayed Job [$PID]"
if [ -d /proc/$PID ]; then
logger -t "monit-dj:$WORKER[$$]" "Dj worker is already running with PID of $PID"
RESULT=1
else
logger -t "monit-dj:$WORKER[$$]" "Removing stale pid file for $WORKER"
rm -f $PID_FILE
fi
fi
fi
if [ $RESULT -eq 0 ]; then
logger -t "monit-dj:$WORKER[$$]" "issuing command $COMMAND in $PWD for $USER"
sudo -u $USER -H /bin/bash -c "$COMMAND" &
NEW_PID=$!
RESULT=$?
logger -t "monit-dj:$WORKER[$$]" "$WORKER started as $NEW_PID : $RESULT"
echo $NEW_PID > $PID_FILE
fi
unlock_and_exit_cleanly
;;
stop)
lock
logger -t "monit_dj:$WORKER[$$]" "Stopping DJ worker:"
if [ -f $PID_FILE ]; then
PID=$(cat $PID_FILE)
# Find children
WORKER_PID=$(ps axo pid,ppid,command|awk '$2=='$PID' {print $1}')
kill -15 $PID $PPID; # kill worker and any child that it may have at this very moment
logger -t "monit-dj:$WORKER[$$]" "Stopping DJ Worker Process $PID $PPID"
SLEEP_COUNT=0
while [ -e /proc/$PID ]; do
sleep .25
let "SLEEP_COUNT+=1"
let "REPORT_TIME = $SLEEP_COUNT%4"
if(( "$SLEEP_COUNT" > $GRACE_TIME )); then
logger -t "monit-dj:$WORKER[$$]" "Stopping DJ Worker Child Process $PID wait exceeded, killing it"
kill -9 $PID 2>/dev/null; true
break
elif(( $REPORT_TIME == 0 ));then
let "RUNTIME = $SLEEP_COUNT/4"
logger -t "monit-dj:$WORKER[$$]" "Waiting for $PID to die ( for $RUNTIME seconds now)"
fi
done
fi
[ -e "$PID_FILE" ] && rm -f $PID_FILE
unlock_and_exit_cleanly
;;
*)
usage
;;
esac
else
echo "/data/$1/current doesn't exist."
usage
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment