about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-06-07 20:45:56 +0000
committerEric Wong <e@80x24.org>2016-06-07 21:03:11 +0000
commit6a65054ce2763d51aca5da525656bcb1f08d61a5 (patch)
tree64ca3ee9d31d513de7fb953297600373db4a2d7b
parent33c2f7794dc72b59390e6199fa0a6f41fb36eeb3 (diff)
Rework the "upgrade" target to only read the PID files once to
avoid misreading the wrong PID files in the middle of the
upgrade.

Additionally, introduce the UPGRADE_DELAY environment parameter
so users can increase/decrease according to their application
startup time.

PID files are inherently racy and people should be using a
process manager (systemd or similar) instead, but this should
mitigate most of the problems with the old target.

While we're at it, add LSB tags for systems which complain
about the lack of them and modernize things a bit using
$(command) construct instead of the more fragile `command`.

Thanks-to: Jesper Rønn-Jensen <jesperrr@gmail.com>
-rw-r--r--examples/init.sh44
1 files changed, 36 insertions, 8 deletions
diff --git a/examples/init.sh b/examples/init.sh
index 1f0e035..4ef6cdc 100644
--- a/examples/init.sh
+++ b/examples/init.sh
@@ -1,7 +1,16 @@
 #!/bin/sh
 set -e
+### BEGIN INIT INFO
+# Provides:          unicorn
+# Required-Start:    $local_fs $network
+# Required-Stop:     $local_fs $network
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Start/stop unicorn Rack app server
+### END INIT INFO
+
 # Example init script, this can be used with nginx, too,
-# since nginx and unicorn accept the same signals
+# since nginx and unicorn accept the same signals.
 
 # Feel free to change any of the following variables for your app:
 TIMEOUT=${TIMEOUT-60}
@@ -9,21 +18,22 @@ APP_ROOT=/home/x/my_app/current
 PID=$APP_ROOT/tmp/pids/unicorn.pid
 CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
 INIT_CONF=$APP_ROOT/config/init.conf
+UPGRADE_DELAY=${UPGRADE_DELAY-2}
 action="$1"
 set -u
 
 test -f "$INIT_CONF" && . $INIT_CONF
 
-old_pid="$PID.oldbin"
+OLD="$PID.oldbin"
 
 cd $APP_ROOT || exit 1
 
 sig () {
-        test -s "$PID" && kill -$1 `cat $PID`
+        test -s "$PID" && kill -$1 $(cat $PID)
 }
 
 oldsig () {
-        test -s $old_pid && kill -$1 `cat $old_pid`
+        test -s "$OLD" && kill -$1 $(cat $OLD)
 }
 
 case $action in
@@ -45,18 +55,36 @@ restart|reload)
         $CMD
         ;;
 upgrade)
-        if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
+        if oldsig 0
+        then
+                echo >&2 "Old upgraded process still running with $OLD"
+                exit 1
+        fi
+
+        cur_pid=
+        if test -s "$PID"
+        then
+                cur_pid=$(cat $PID)
+        fi
+
+        if test -n "$cur_pid" &&
+                        kill -USR2 "$cur_pid" &&
+                        sleep $UPGRADE_DELAY &&
+                        new_pid=$(cat $PID) &&
+                        test x"$new_pid" != x"$cur_pid" &&
+                        kill -0 "$new_pid" &&
+                        kill -QUIT "$cur_pid"
         then
                 n=$TIMEOUT
-                while test -s $old_pid && test $n -ge 0
+                while kill -0 "$cur_pid" 2>/dev/null && test $n -ge 0
                 do
                         printf '.' && sleep 1 && n=$(( $n - 1 ))
                 done
                 echo
 
-                if test $n -lt 0 && test -s $old_pid
+                if test $n -lt 0 && kill -0 "$cur_pid" 2>/dev/null
                 then
-                        echo >&2 "$old_pid still exists after $TIMEOUT seconds"
+                        echo >&2 "$cur_pid still running after $TIMEOUT seconds"
                         exit 1
                 fi
                 exit 0