Last active 6 months ago

Revision 3200352071eeed6a9f403173f9e68cc1ebb9c815

node_debian_init.sh Raw
1#! /bin/sh
2# ------------------------------------------------------------------------------
3# SOME INFOS : fairly standard (debian) init script.
4# Note that node doesn't create a PID file (hence --make-pidfile)
5# has to be run node in the background (hence --background)
6# and NOT as root (hence --chuid)
7#
8# MORE INFOS : INIT SCRIPT http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit
9# INIT-INFO RULES http://wiki.debian.org/LSBInitScripts
10# INSTALL/REMOVE http://www.debian-administration.org/articles/28
11# ------------------------------------------------------------------------------
12## BEGIN <MODIFY TO REFLECT YOUR SETTINGS> ##
13#
14# 1) Don't forget to also modify the COMMENTED fields in the "### BEGIN INIT INFO"
15# below (don't uncomment them)
16# to reflect your setting before issuing update-rc.d
17# eg: provides, Short-Description, Description
18#
19# 2) in case you have different node.js servers running, each init.d script should
20# (obviously) have a unique name so that PIDS do not conflict
21# --> name them accordingly
22# eg: node_static_server, node_express1, node_load_balancer.sh...
23#
24# 3) copy the renamed/modified script(s) to /etc/init.d
25# chmod 755,
26# INSTALL : update-rc.d scriptname defaults
27# UNINSTALL : update-rc.d -f scriptname remove
28# ______________________________________________________________________________
29### BEGIN INIT INFO
30# Provides: nodeserver
31# Required-Start: $remote_fs $named $syslog
32# Required-Stop: $remote_fs $named $syslog
33# Default-Start: 2 3 4 5
34# Default-Stop: 0 1 6
35# Short-Description: DEBIAN initscript for node.js servers/apps
36# Description: ex : proxy server is a node.js http server listening on
37# port 8080 (relayed from 80 by iptables). It balances
38# http requests between the main nodejs server
39# (nodejs.oghme.com:8000), the static file-server
40# (static.oghme.com) and the legacy apache server
41# (apache.oghme.com) and possibly other servers
42# place this file in /etc/init.d.
43### END INIT INFO
44
45# Author: Peter Host <peterhost+oghme@virtualregions.com>
46#
47# Please remove the "Author" lines above and replace them
48# with your own name if you copy and modify this script.
49# ______________________________________________________________________________
50#
51# PATH should only include /usr/* if it runs after the mountnfs.sh script
52PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin # modify if you need
53
54
55DESC="node.js http server" # whatever fancy description you like
56
57NODEUSER=tomneale:tomneale # USER who OWNS the daemon process (no matter whoever runs the init script)
58 # user:group (if no group is specified, the primary GID for that user is used)
59
60LOCAL_VAR_RUN=/usr/local/var/run # in case the init script is run by non-root user, you need to
61 # indicate a directory writeable by $NODEUSER to store the PID file
62 # NB : 1) /usr/local/var/run does not exist by DEFAULT. Either create it
63 # or choose one of your own liking.
64 # 2) node, npm,... are best NOT installed/run as ROOT.
65 # (see here: https://github.com/isaacs/npm/blob/master/README.md)
66
67NAME=node # name of the node.js executable
68DAEMON=/usr/local/bin/$NAME # this SHOULD POINT TO where your node executable is
69DAEMON_ARGS="/home/tomneale/STATIC/app.js" # your node.js server/app goes here
70 # NB: don't use ~/ in path
71
72## END </MODIFY TO REFLECT YOUR SETTINGS> ##
73## (Nothing else to modify from this point on...) ##
74# ------------------------------------------------------------------------------
75
76
77# Do NOT "set -e"
78
79[ $UID -eq "0" ] && LOCAL_VAR_RUN=/var/run # in case this script is run by root, override user setting
80THIS_ARG=$0
81INIT_SCRIPT_NAME=`basename $THIS_ARG`
82INIT_SCRIPT_NAME_NOEXT=${INIT_SCRIPT_NAME%.*}
83PIDFILE="$LOCAL_VAR_RUN/$INIT_SCRIPT_NAME_NOEXT.pid"
84SCRIPTNAME=/etc/init.d/$INIT_SCRIPT_NAME
85
86# Exit if the package is not installed
87[ -x "$DAEMON" ] || { echo "can't find Node.js ($DAEMON)" >&2; exit 0; }
88
89# Exit if the 'run' folder is not present
90[ -d "$LOCAL_VAR_RUN" ] || { echo "Directory $LOCAL_VAR_RUN does not exist. Modify the '$INIT_SCRIPT_NAME_NOEXT' init.d script ($THIS_ARG) accordingly" >&2; exit 0; }
91
92# Read configuration variable file if it is present
93[ -r /etc/default/$INIT_SCRIPT_NAME ] && . /etc/default/$INIT_SCRIPT_NAME
94
95# Load the VERBOSE setting and other rcS variables
96. /lib/init/vars.sh
97
98# Define LSB log_* functions.
99# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
100. /lib/lsb/init-functions
101
102# REMOVE THAT !!!
103VERBOSE=yes
104
105#
106# Function that starts the daemon/service
107#
108do_start()
109{
110 # Return
111 # 0 if daemon has been started
112 # 1 if daemon was already running
113 # 2 if daemon could not be started
114 start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $NODEUSER --background --exec $DAEMON --test > /dev/null \
115 || { [ "$VERBOSE" != no ] && log_daemon_msg " ---> Daemon already running $DESC" "$INIT_SCRIPT_NAME_NOEXT"; return 1; }
116 start-stop-daemon --start --quiet --chuid $NODEUSER --make-pidfile --pidfile $PIDFILE --background --exec $DAEMON -- \
117 $DAEMON_ARGS \
118 || { [ "$VERBOSE" != no ] && log_daemon_msg " ---> could not be start $DESC" "$INIT_SCRIPT_NAME_NOEXT"; return 2; }
119 # Add code here, if necessary, that waits for the process to be ready
120 # to handle requests from services started subsequently which depend
121 # on this one. As a last resort, sleep for some time.
122 [ "$VERBOSE" != no ] && log_daemon_msg " ---> started $DESC" "$INIT_SCRIPT_NAME_NOEXT"
123}
124
125#
126# Function that stops the daemon/service
127#
128do_stop()
129{
130 # Return
131 # 0 if daemon has been stopped
132 # 1 if daemon was already stopped
133 # 2 if daemon could not be stopped
134 # other if a failure occurred
135 start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --chuid $NODEUSER --name $DAEMON
136 RETVAL="$?"
137 [ "$VERBOSE" != no ] && [ "$RETVAL" = 1 ] && log_daemon_msg " ---> SIGKILL failed => hardkill $DESC" "$INIT_SCRIPT_NAME_NOEXT"
138 [ "$RETVAL" = 2 ] && return 2
139 # Wait for children to finish too if this is a daemon that forks
140 # and if the daemon is only ever run from this initscript.
141 # If the above conditions are not satisfied then add some other code
142 # that waits for the process to drop all resources that could be
143 # needed by services started subsequently. A last resort is to
144 # sleep for some time.
145 start-stop-daemon --stop --quiet --oknodo --retry=0/3/KILL/5 --pidfile $PIDFILE --chuid $NODEUSER --exec $DAEMON -- $DAEMON_ARGS
146 [ "$?" = 2 ] && return 2
147 # Many daemons don't delete their pidfiles when they exit.
148 rm -f $PIDFILE
149 [ "$VERBOSE" != no ] && [ "$RETVAL" = 1 ] && log_daemon_msg " ---> $DESC not running" "$INIT_SCRIPT_NAME_NOEXT"
150 [ "$VERBOSE" != no -a "$RETVAL" = 0 ] && log_daemon_msg " ---> $DESC stopped" "$INIT_SCRIPT_NAME_NOEXT"
151 return "$RETVAL"
152}
153
154#
155# Function that sends a SIGHUP to the daemon/service
156#
157do_reload() {
158 #
159 # If the daemon can reload its configuration without
160 # restarting (for example, when it is sent a SIGHUP),
161 # then implement that here.
162 #
163 start-stop-daemon --stop --quiet --signal 1 --pidfile $PIDFILE --chuid $NODEUSER --name $NAME
164 return 0
165}
166
167#
168# Function that returns the daemon
169#
170do_status() {
171 #
172 # http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
173 # 0 program is running or service is OK
174 # 1 program is dead and /var/run pid file exists
175 # (2 program is dead and /var/lock lock file exists) (not used here)
176 # 3 program is not running
177 # 4 program or service status is unknown
178 RUNNING=$(running)
179
180 # $PIDFILE corresponds to a live $NAME process
181 ispidactive=$(pidof $NAME | grep `cat $PIDFILE 2>&1` >/dev/null 2>&1)
182 ISPIDACTIVE=$?
183
184 if [ -n "$RUNNING" ]; then
185 if [ $ISPIDACTIVE ]; then
186 log_success_msg "$INIT_SCRIPT_NAME_NOEXT ($NODEUSER) is running"
187 exit 0
188 fi
189 else
190 if [ -f $PIDFILE ]; then
191 log_success_msg "$INIT_SCRIPT_NAME_NOEXT ($NODEUSER) is not running, phantom pidfile $PIDFILE"
192 exit 1
193 else
194 log_success_msg "$INIT_SCRIPT_NAME_NOEXT ($NODEUSER) is not running"
195 exit 3
196 fi
197 fi
198
199}
200
201running() {
202 RUNSTAT=$(start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $NODEUSER --background --exec $DAEMON --test > /dev/null)
203 if [ "$?" = 1 ]; then
204 echo y
205 fi
206
207}
208
209
210case "$1" in
211 start)
212 [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$INIT_SCRIPT_NAME_NOEXT"
213 do_start
214 case "$?" in
215 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
216 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
217 esac
218 ;;
219 stop)
220 [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$INIT_SCRIPT_NAME_NOEXT"
221 do_stop
222 case "$?" in
223 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
224 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
225 esac
226 ;;
227 #reload|force-reload)
228 #
229 # If do_reload() is not implemented then leave this commented out
230 # and leave 'force-reload' as an alias for 'restart'.
231 #
232 #log_daemon_msg "Reloading $DESC" "$NAME"
233 #do_reload
234 #log_end_msg $?
235 #;;
236 restart|force-reload)
237 #
238 # If the "reload" option is implemented then remove the
239 # 'force-reload' alias
240 #
241 log_daemon_msg "Restarting $DESC" "$INIT_SCRIPT_NAME_NOEXT"
242 do_stop
243 case "$?" in
244 0|1)
245 do_start
246 case "$?" in
247 0) log_end_msg 0 ;;
248 1) log_end_msg 1 ;; # Old process is still running
249 *) log_end_msg 1 ;; # Failed to start
250 esac
251 ;;
252 *)
253 # Failed to stop
254 log_end_msg 1
255 ;;
256 esac
257 ;;
258 status)
259 do_status
260 ;;
261 *)
262 #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
263 echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
264 exit 3
265 ;;
266esac
267
268exit 0
269