Skip to content

Instantly share code, notes, and snippets.

@neurocis
Last active August 29, 2015 14:10
Show Gist options
  • Save neurocis/4dd76f127b7ee3215918 to your computer and use it in GitHub Desktop.
Save neurocis/4dd76f127b7ee3215918 to your computer and use it in GitHub Desktop.
init base script for *nix distributions to start, stop restart a daemon-ized nodejs app in forever running under a specific user / account.
#!/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/
# and then further customized by: Leigh Phillips <neurocis@neurocis.me>
#
# 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"
# The directory where the app works out of.
# WORKINGDIR="/where/this/will/be/ran"
# The application startup Javascript file path.
# APPLICATION_PATH="/home/user/my-application/start-my-application.js"
# The user account you want the process to run under.
# SUDO_USER="{MyUserToRunAs}"
# 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="AppName"
NODE_BIN_DIR="/usr/bin"
NODE_PATH="/usr/lib/node_modules"
WORKINGDIR="/where/this/will/be/ran"
APPLICATION_PATH="/where/the/app/resides"
SUDO_USER="{MyUserToRunAs}"
# When running as a user you do not have access to /var/log so suggest the following:
PIDFILE="/home/{MyUerToRanAs}/.forever/pids/$NAME.pid"
LOGFILE="/home/{MyUserToRunAs}/.forever/$NAME.log"
MIN_UPTIME="5000"
SPIN_SLEEP_TIME="2000"
# 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() {
echo "Starting $NAME"
# 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.
/usr/bin/sudo -u $SUDO_USER $NODE_BIN_DIR/forever \
--workingDir $WORKINGDIR \
--pidFile $PIDFILE \
-a \
-l $LOGFILE \
--minUptime $MIN_UPTIME \
--spinSleepTime $SPIN_SLEEP_TIME \
start $APPLICATION_PATH 2>&1 > /dev/null &
RETVAL=$?
}
stop() {
if [ -f $PIDFILE ]; then
echo "Shutting down $NAME"
# Tell Forever to stop the process.
/usr/bin/sudo -u $SUDO_USER $NODE_BIN_DIR/forever stop $APPLICATION_PATH 2>&1 > /dev/null
# Get rid of the pidfile, since Forever won't do that.
rm -f $PIDFILE
RETVAL=$?
else
echo "$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 "$NAME is running."
RETVAL=0
else
echo "$NAME is not running."
RETVAL=3
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
restart
;;
*)
echo "Usage: {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment