#!/bin/bash {% if osflavor=='centos' %} # # /etc/rc.d/init.d/{{service}} # # {{service}} - Provisioned using forever-service # # chkconfig: 2345 90 10 # description: forever-service startup script for node script based service {{service}}, uses forever to start the service # {% else %} ### BEGIN INIT INFO # Provides: {{service}} # 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 {{service}} # Description: forever-service startup script for node script based service {{service}}, uses forever to start the service ### END INIT INFO {% endif %} # CLI {{cli}} # Working Directory {{cwd}} #Setup Environment variables (if any) {% if envVarsArray|default(false) %} {% for v in envVarsArray %} export {{ v }} {% endfor %} {% endif %} # Check if any of $pid (could be plural) are running LOGFILE="/var/log/{{service}}.log" {% if osflavor === 'centos' %} LOCKFILE="/var/lock/subsys/{{service}}" {% else %} LOCKFILE="/var/lock/{{service}}" {% endif %} # introduce some gaps between restarts and throttle continous restarts MIN_UPTIME="{{minUptime|default('5000')}}" SPIN_SLEEP_TIME="{{spinSleepTime|default('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="{{killSignal|default('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={{forceKillWaitTime|default('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={{foreverRoot}} {% if runAsUser %} STATUS=$({{suprog}} - {{runAsUser}} -c "export FOREVER_ROOT={{foreverRoot}};{% if envVarsNameValueArray|default(false) %}{% for v in envVarsNameValueArray %}export {{ v[0] }}=$(printf "%q" {{v[1]}});{% endfor %}{% endif %}{{foreverPath}}forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\({{service}}\)\s.*\)/\2-status:\1/;tx;d;:x'") {% else %} STATUS=$({{foreverPath}}forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\({{service}}\)\s.*\)/\2-status:\1/;tx;d;:x') {% endif %} if ! [ -z "$STATUS" ]; then echo "Service {{service}} already running" return 0 fi echo "Starting {{service}}" {% if runAsUser %} touch $LOGFILE chown {{runAsUser}} $LOGFILE {{suprog}} - {{runAsUser}} -c "\ export FOREVER_ROOT={{foreverRoot}};\ {% if envVarsNameValueArray|default(false) %}{% for v in envVarsNameValueArray %}export {{ v[0] }}=$(printf "%q" {{v[1]}});\{% endfor %}{% else %}\{% endif %} cd {{cwd}};\{% if applyUlimits %} ulimit -f unlimited;\ ulimit -t unlimited;\ ulimit -v unlimited;\ ulimit -n 64000;\ ulimit -m unlimited;\ ulimit -u 32000;\{% endif %} {{foreverPath}}forever \ -a \ -l $LOGFILE \ --minUptime $MIN_UPTIME \ --spinSleepTime $SPIN_SLEEP_TIME \ --killSignal $KILL_SIGNAL \ {{foreverOptions|default('')}} \ --uid {{service}} \ start {{script|default('app.js')}} {{scriptOptions|default('')}}" 2>&1 >/dev/null {% else %} # move to the directory from where the inital forever script was launched so that even if it is relative it works as expected cd {{cwd}} {% if applyUlimits %} ulimit -f unlimited ulimit -t unlimited ulimit -v unlimited ulimit -n 64000 ulimit -m unlimited ulimit -u 32000 {% endif %} {{foreverPath}}forever \ -a \ -l $LOGFILE \ --minUptime $MIN_UPTIME \ --spinSleepTime $SPIN_SLEEP_TIME \ --killSignal $KILL_SIGNAL \ {{foreverOptions|default('')}} \ --uid {{service}} \ start {{script|default('app.js')}} {{scriptOptions|default('')}} 2>&1 >/dev/null {% endif %} 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={{foreverRoot}} echo -n "Shutting down {{service}}: " {% if runAsUser %} STATUS=$({{suprog}} - {{runAsUser}} -c "export FOREVER_ROOT={{foreverRoot}};{% if envVarsNameValueArray|default(false) %}{% for v in envVarsNameValueArray %}export {{ v[0] }}=$(printf "%q" {{v[1]}});{% endfor %}{% endif %}{{foreverPath}}forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\({{service}}\)\s.*\)/\2-status:\1/;tx;d;:x'") {% else %} STATUS=$({{foreverPath}}forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\({{service}}\)\s.*\)/\2-status:\1/;tx;d;:x') {% endif %} 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 {% if runAsUser %} PID=$({{suprog}} - {{runAsUser}} -c "export FOREVER_ROOT={{foreverRoot}};{% if envVarsNameValueArray|default(false) %}{% for v in envVarsNameValueArray %}export {{ v[0] }}=$(printf "%q" {{v[1]}});{% endfor %}{% endif %}{{foreverPath}}forever --plain list | sed -n -e '/data:\s*\[[0-9]*\]\s\({{service}}\)\s/p' | awk '{print \$7}'") {% else %} PID=$({{foreverPath}}forever --plain list | sed -n -e '/data:\s*\[[0-9]*\]\s\({{service}}\)\s/p' | awk '{print $7}') {% endif %} 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 {% if runAsUser %} {{suprog}} - {{runAsUser}} -c "{{foreverPath}}forever stop {{service}}" 2>&1 >/dev/null & {% else %} {{foreverPath}}forever stop {{service}} 2>&1 >/dev/null & {% endif %} 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 {% if osflavor === 'centos' %} usleep 500000 let CURRENTWAITTIME-=500 {% else %} sleep 1 CURRENTWAITTIME=$(( $CURRENTWAITTIME - 1000)) {% endif %} 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={{foreverRoot}} {% if runAsUser %} STATUS=$({{suprog}} - {{runAsUser}} -c "export FOREVER_ROOT={{foreverRoot}};{% if envVarsNameValueArray|default(false) %}{% for v in envVarsNameValueArray %}export {{ v[0] }}=$(printf "%q" {{v[1]}});{% endfor %}{% endif %}{{foreverPath}}forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\({{service}}\)\s.*\)/\2-status:\1/;tx;d;:x'") {% else %} STATUS=$({{foreverPath}}forever --plain list | sed 's/data:\(\s*\[[0-9]*\]\s*\({{service}}\)\s.*\)/\2-status:\1/;tx;d;:x') {% endif %} if [ -z "$STATUS" ]; then echo "{{service}} 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: {start|stop|status|restart}" exit 1 ;; esac exit $?