Multiple node.js applications, same server

2014-12-13 • 2 min read • Tags: Sysadm

Today I had to setup a hastebin instance on a server where etherpad-lite was already running.

I had already written a basic init.d script for the RedHat server, inspired by a Fedora template. The problem was that it was now catching the other node instance:

# ps aux | grep node
pastebin  3194  0.0  0.1 643752 28080 ?        Sl   Dec12   0:00 /soft/bin/node server.js
etherpad 12257  0.0  0.4 724892 69912 ?        Sl   Dec12   0:04 /soft/bin/node
node_modules/ep_etherpad-lite/node/server.js

The good solution is probably to use a fancy process manager like foreman. Still I wanted to stick to a basic solution. So I decided to go with the  `status -p` and `killproc -p` functions (see `/etc/rc.d/init.d/functions`), for the status and stop commands respectively. These function handle our pid file nicely.

But how to get the pid from the daemon function ?

The solution I came up with is to use a subscript that just start the node application and catches the pid:

#!/bin/sh
# We need to store pid for init.d scripts.
basedir=$(dirname $0)
cd $basedir
/soft/64/bin/node server.js &
echo $! > tmp/pids/hastebin.pid

Here is the whole script:

#!/bin/sh
### BEGIN INIT INFO
# Provides: hastebin
# Required-Start: $local_fs $remote_fs redis
# Required-Stop: $local_fs $remote_fs redis
# Default-Start: 3 4 5
# Default-Stop: 0 1 6
# Short-Description: hastebin initscript
# Description: hastebin is a collaboration editor.
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

progname="Hastebin"
path="/sites/pastebin/www/htdocs/haste-server"
prog="hastebin"
parameter=""
log="$path/log/error.log"
conf="$path/config.js"
user="pastebin"
pidfile="$path/tmp/pids/$prog.pid"
lockfile="/var/lock/subsys/$prog"

progpath=$path/$prog
logpath=$(dirname $log)

start() {
 [ -x $progpath ] || exit 5
        [ -f $conf ] || exit 6
        [ -d $logpath ] || mkdir $logpath
        [ -f $log ] || touch $log
        chown $user $logpath
        chown $user $log

        echo -n $"Starting $progname: "
        daemon --user=$user --pidfile=$pidfile "$progpath $parameter >>$log 2>&1 &"
        retval=$?
        echo
        [ $retval -eq 0 ] && touch $lockfile
        return $retval
}

stop() {
        echo -n $"Stopping $progname: "
        killproc -p $pidfile $prog
        retval=$?
        echo
        [ $retval -eq 0 ] && rm -f $lockfile
        return $retval
}

restart() {
        stop
        start
}

rh_status() {
        status -p $pidfile $prog
}

rh_status_q() {
        rh_status >/dev/null 2>&1
}

case "$1" in
        start)
                rh_status_q && exit 0
                $1
        ;;
        stop)
                rh_status_q || exit 0
                $1
        ;;
        restart)
                $1
        ;;
        status)
                rh_status
        ;;
        *)
                echo $"Usage: $0 {start|stop|status|restart}"
                exit 2
esac

Now the next enhancement is probably to use a unique parametrized init file, and create links in /etc/init.d to it.