Skip to content

Instantly share code, notes, and snippets.

@faiwer
Created June 20, 2017 08:18
Show Gist options
  • Save faiwer/d3e4a417b842ff8223bd1caae913b29a to your computer and use it in GitHub Desktop.
Save faiwer/d3e4a417b842ff8223bd1caae913b29a to your computer and use it in GitHub Desktop.
#!/bin/bash
### BEGIN INIT INFO
# Provides: %name%
# Required-Start: $network $remote_fs $local_fs
# Required-Stop: $network $remote_fs $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: forever-service startup script for %name%
# Description: forever-service startup script for node script based service %name%, uses forever to start the service
### END INIT INFO
# CLI /usr/bin/nodejs /usr/bin/forever-service install -s index.js -r bilim %name%
# Working Directory /home/bilim/constructor-server
#Setup Environment variables (if any)
# Check if any of $pid (could be plural) are running
LOGFILE="/var/log/%name%.log"
LOCKFILE="/var/lock/%name%"
# introduce some gaps between restarts and throttle continous restarts
MIN_UPTIME="5000"
SPIN_SLEEP_TIME="2000"
# kill signal: Since default needs to be SIGTERM, it is important that services gracefully shutdown,
# specially if they are doing transactions or other work which should not be interuppted in between
# for exceptional situation where you dont care about abrupt shutdown, SIGKILL should be used
KILL_SIGNAL="SIGTERM"
# Wait time afer with SIGKILL will be sent to the process, in case SIGTERM is not fully finished
# This is required since when we use SIGTERM, some times if there is problem in code, it might take lot of time for process to exit
# or process may never exit, in such siutation we have to forcebly kill it so that shutdown or service restart can be done appropriately
# this wait time is in millisecond
KILLWAITTIME=5000
killtree() {
local _pid=$1
local _sig=${2:--TERM}
kill -stop ${_pid} # needed to stop quickly forking parent from producing children between child killing and parent killing
for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
killtree ${_child} ${_sig}
done
kill -${_sig} ${_pid}
}
checkpidexists() {
[ -d "/proc/$1" ] && return 0
return 1
}
start() {
#this is to ensure forever is able to find out the correct root every time
export FOREVER_ROOT=/home/bilim/.forever
STATUS=$(su - bilim -c "export FOREVER_ROOT=/home/bilim/.forever;/usr/bin/forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\(%name%\)\s.*\)/\2-status:\1/;tx;d;:x'")
if ! [ -z "$STATUS" ]; then
echo "Service %name% already running"
return 0
fi
echo "Starting %name%"
touch $LOGFILE
chown bilim $LOGFILE
su - bilim -c "\
export FOREVER_ROOT=/home/bilim/.forever;\
\
cd /home/bilim/constructor-server;\
/usr/bin/forever \
-a \
-l $LOGFILE \
--minUptime $MIN_UPTIME \
--spinSleepTime $SPIN_SLEEP_TIME \
--killSignal $KILL_SIGNAL \
\
--uid %name% \
start index.js " 2>&1 >/dev/null
RETVAL=$?
[ $RETVAL = 0 ] && touch $LOCKFILE
return $RETVAL
}
stop() {
#this is to ensure forever is able to find out the correct root every time
export FOREVER_ROOT=/home/bilim/.forever
echo -n "Shutting down %name%: "
STATUS=$(su - bilim -c "export FOREVER_ROOT=/home/bilim/.forever;/usr/bin/forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\(%name%\)\s.*\)/\2-status:\1/;tx;d;:x'")
if [ -z "$STATUS" ]; then
echo "Not running"
return 0
fi
# PID=$(<$PIDFILE) - Changed to detection based on actual PID from forever, sicne due to watchDirectory pid could dynamically change
PID=$(su - bilim -c "export FOREVER_ROOT=/home/bilim/.forever;/usr/bin/forever --plain list | sed -n -e '/data:\s*\[[0-9]*\]\s\(%name%\)\s/p' | awk '{print \$7}'")
if [ -z "$PID" ]; then
echo "Could not get pid"
return 0
fi
#run in background, since recent changes in forever, now blocks stop call with SIGTERM is finished
#but we want to wait till some time and forcibly kill after elapsed time
#without background script, we could be waiting forever
su - bilim -c "/usr/bin/forever stop %name%" 2>&1 >/dev/null &
CURRENTWAITTIME=$KILLWAITTIME
# wait for some time before forcefully killing the process
while [ $CURRENTWAITTIME -gt 0 ]; do
#check if the process is still running
checkpidexists $PID
if [ $? -ne 0 ]; then
# if not running we can break, since no more wait is needed, service is stopped
echo "Successful"
break
fi
sleep 1
CURRENTWAITTIME=$(( $CURRENTWAITTIME - 1000))
done
checkpidexists $PID
if [ $? -eq 0 ]; then
killtree $PID 9
echo 'Forced shutdown'
fi
rm -f $PIDFILE 2>&1 >/dev/null
rm -f $LOCKFILE 2>&1 >/dev/null
return 0
}
status() {
#this is to ensure forever is able to find out the correct root every time
export FOREVER_ROOT=/home/bilim/.forever
STATUS=$(su - bilim -c "export FOREVER_ROOT=/home/bilim/.forever;/usr/bin/forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\(%name%\)\s.*\)/\2-status:\1/;tx;d;:x'")
if [ -z "$STATUS" ]; then
echo "%name% is not running"
RETVAL=3
else
echo $STATUS
RETVAL=0
fi
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
echo "Usage: <servicename> {start|stop|status|restart}"
exit 1
;;
esac
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment