Improved article: Generate init.d script for Node apps
Working example for Node app as a debian/ubuntu daemon.
You need Node's forever
module, installed as: -g
npm install -g forever
file: themeoccurrenced.sh
#!/bin/bash
#
# An init.d script for running a Node.js process as a service using Forever as
# the process monitor. For more configuration options associated with Forever,
# see: https://github.com/nodejitsu/forever
#
# This was written for Debian distributions such as Ubuntu, but should still
# work on RedHat, Fedora, or other RPM-based distributions, since none of the
# built-in service functions are used. So information is provided for both.
#
### BEGIN INIT INFO
# Provides: my-application
# Required-Start: $syslog $remote_fs
# Required-Stop: $syslog $remote_fs
# Should-Start: $local_fs
# Should-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: My Application
# Description: My Application
### END INIT INFO
#
### BEGIN CHKCONFIG INFO
# chkconfig: 2345 55 25
# description: My Application
### END CHKCONFIG INFO
#
# Based on:
# https://gist.github.com/3748766
# https://github.com/hectorcorrea/hectorcorrea.com/blob/master/etc/forever-initd-hectorcorrea.sh
# https://www.exratione.com/2011/07/running-a-nodejs-server-as-a-service-using-forever/
#
# The example environment variables below assume that Node.js is installed by
# building from source with the standard settings.
#
# It should be easy enough to adapt to the paths to be appropriate to a package
# installation, but note that the packages available in the default repositories
# are far behind the times. Most users will be building from source to get a
# suitably recent Node.js version.
#
# An application name to display in echo text.
# NAME="My Application"
# The full path to the directory containing the node and forever binaries.
# NODE_BIN_DIR="/usr/local/node/bin"
# Set the NODE_PATH to the Node.js main node_modules directory.
# NODE_PATH="/usr/local/lib/node_modules"
# Process ID easier to identify and shutdown
# FOREVER_ID="forever-anynameyouwant"
# Source Directory where node application is
# APPLICATION_SOURCE_DIR="/data01/themoccurrence"
# The application startup Javascript file path relative to APPLICATION_SOURCE_DIR.
# APPLICATION_PATH="start-my-application.js"
# Process ID file path.
# PIDFILE="/var/run/my-application.pid"
# Log file path.
# LOGFILE="/var/log/my-application.log"
# Forever settings to prevent the application spinning if it fails on launch.
# MIN_UPTIME="5000"
# SPIN_SLEEP_TIME="2000"
NAME="Themoccurrence.js"
NODE_BIN_DIR="$(dirname `which node`)"
NODE_PATH="/usr/lib/node_modules"
FOREVER_ID="forever-themoccurrence"
APPLICATION_SOURCE_DIR="/data01/themoccurrence"
APPLICATION_PATH="bin/www"
PIDFILE="/var/run/themoccurrence.pid"
LOGFILE="/data01/logs/themoccurrence.log"
MIN_UPTIME="5000"
SPIN_SLEEP_TIME="2000"
PORT=80
# Add node to the path for situations in which the environment is passed.
PATH=$NODE_BIN_DIR:$PATH
# Export all environment variables that must be visible for the Node.js
# application process forked by Forever. It will not see any of the other
# variables defined in this script.
export NODE_PATH=$NODE_PATH
start() {
# We're calling forever directly without using start-stop-daemon for the
# sake of simplicity when it comes to environment, and because this way
# the script will work whether it is executed directly or via the service
# utility.
#
# The minUptime and spinSleepTime settings stop Forever from thrashing if
# the application fails immediately on launch. This is generally necessary to
# avoid loading development servers to the point of failure every time
# someone makes an error in application initialization code, or bringing down
# production servers the same way if a database or other critical service
# suddenly becomes inaccessible.
#
# The pidfile contains the child process pid, not the forever process pid.
# We're only using it as a marker for whether or not the process is
# running.
#
# Note that redirecting the output to /dev/null (or anywhere) is necessary
# to make this script work if provisioning the service via Chef.
echo `forever list` | grep -q "$FOREVER_ID"
if [ "$?" -eq "0" ]; then
echo "(${whoami}) $NAME is already running."
RETVAL=0
else
echo "(${whoami}) Starting $NAME"
echo "" > $LOGFILE
export PORT=$PORT
forever \
--id $FOREVER_ID \
--pidFile $PIDFILE \
-a \
-l $LOGFILE \
--minUptime $MIN_UPTIME \
--spinSleepTime $SPIN_SLEEP_TIME \
start --sourceDir $APPLICATION_SOURCE_DIR $APPLICATION_PATH 2>&1 > /dev/null &
RETVAL=$?
fi
}
stop() {
if [ -f $PIDFILE ]; then
echo "(${whoami}) Shutting down $NAME"
# Tell Forever to stop the process.
# forever stop --sourceDir $APPLICATION_SOURCE_DIR $APPLICATION_PATH 2>&1 > /dev/null
forever stop $FOREVER_ID 2>&1 > /dev/null
# Get rid of the pidfile, since Forever won't do that.
rm -f $PIDFILE
RETVAL=$?
else
echo "(${whoami}) $NAME is not running."
RETVAL=0
fi
}
restart() {
stop
start
}
status() {
# On Ubuntu this isn't even necessary. To find out whether the service is
# running, use "service my-application status" which bypasses this script
# entirely provided you used the service utility to start the process.
#
# The commented line below is the obvious way of checking whether or not a
# process is currently running via Forever, but in recent Forever versions
# when the service is started during Chef provisioning a dead pipe is left
# behind somewhere and that causes an EPIPE exception to be thrown.
# forever list | grep -q "$APPLICATION_PATH"
#
# So instead we add an extra layer of indirection with this to bypass that
# issue.
echo `forever list` | grep -q "$APPLICATION_PATH"
if [ "$?" -eq "0" ]; then
echo "(${whoami}) $NAME is running."
RETVAL=0
else
echo "(${whoami}) $NAME is not running."
RETVAL=3
fi
}
log() {
tail -f $LOGFILE
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
restart
;;
log)
log
;;
*)
echo "Usage: {start|stop|status|restart|log}"
exit 1
;;
esac
exit $RETVAL