Desplegar una aplicación Node.js como servicio systemd (demonio)

En el mundo linux hay dos gestores de demonios que se suelen usar en casi todas las distribuciones. Upstart o systemd.

Si lo que quieres es crear un demonio para Ubuntu o cualquier otro SO que use Upstart, tienes que leer este articulo, y si lo que quieres es crear el demonio para Debian u otros que usen systemd, sigue leyendo este post.

Vamos al lio. Para nuestro demonio vamos a necesitar 3 cosas: forever, un script para crear el servicio y un script para avisar a monit para que mire nuestro servicio y lo reinicie si se cae.

El script del servicio

Como me gusta ponértelo fácil, voy a obviar la explicación y simplemente les digo que copies el siguiente código y lo pegues dentro de un archivo que se llame como el servicio que quieres crear dentro de /etc/init.d/my-service (por ejemplo).

Dentro de este archivo solo tienes que tocar dos o tres cosas al principio del archivo en la zona de configuración. Es fácil, básicamente es poner el nombre del servicio (en mi ejemplo es “my-service”), el directorio donde está alojado, y el nombre del archivo principal de la aplicación.
Hay algunas cositas mas que se pueden configurar, pero en general con esto basta.

#!/bin/bash
# This service requires you have forever app installed in your system.
### CONFIG ZONE
# This is the service name. It cant have any special char or space.
serviceName="my-service"
# Where is located your app
appFilePath="/var/node/my-service-node-app"
# Whats the name of your main app file.
appIndex="app.js"
enviroment=production
### END CONFIG ZONE
###### DO NOT EDIT BELOW THIS LINE ######
# Source function library.
. /lib/lsb/init-functions
pidFile="/var/run/$serviceName.pid"
logFile="/var/run/$serviceName.log"
command="node"
nodeApp="$appFilePath/$appIndex"
foreverApp="forever"
start() {
	echo "Starting $serviceName"
	PATH=/usr/local/bin:$PATH
	export NODE_ENV=$enviroment
	$foreverApp start --pidFile $pidFile -l $logFile -a -d -c "$command" $nodeApp
	RETVAL=$?
}
restart() {
	echo -n "Restarting $serviceName"
	$foreverApp restart $nodeApp
	RETVAL=$?
}
stop() {
	echo -n "Shutting down $serviceName"
	$foreverApp stop $nodeApp
	RETVAL=$?
}
status() {
   echo -n "Status $serviceName"
   $foreverApp list
   RETVAL=$?
}
case "$1" in
   start)
        start
        ;;
    stop)
        stop
        ;;
   status)
        status
       ;;
   restart)
   	restart
        ;;
	*)
       echo "Usage:  {start|stop|status|restart}"
       exit 1
        ;;
esac
exit $RETVAL

Tambien dejo el gist para que cualquier mejora que quieras añadir lo hagas por esta via.
https://gist.github.com/capynet/2de13de81ef8a71f2b2f

Ya tenemos servicio! ¿Y como lo usamos?. Pues como cualquier servicio:

sudo service my-service start
sudo service my-service stop
sudo service my-service restart
sudo service my-service status

Esto debería alcanzar, pero no. Este demonio no sabe volver a arrancarse si la aplicación de nodejs se para. Esa parte la vamos a solucionar usando monit.

Configurar monit

El rol de monit es el de “mirar” todo el tiempo al demonio que creamos anteriormente, y arrancarlo si este se muere.

En Debian y la mayoría de distros, a los archivos de configuración que tenemos que crear (uno por demonio) los pondremos en “/etc/monit/monitrc.d/“.
Yo por lo general creo un archivo con el formato monit-[MI-SERVICIO].conf.

Dentro de este archivo SIEMRPE vamos a usar el siguiente formato, así que simplemente cópialo, pon el nombre del demonio y el puerto, guarda los cambios, reinicia monit y listo.

check process my-service with pidfile "/var/run/my-service.pid"
        start program = "/etc/init.d/my-service start"
        stop program = "/etc/init.d/my-service stop"
        if failed
                port [THE NODEJS PORT HERE] protocol HTTP
                request / with timeout 10 seconds
        then restart

De nuevo, aqui está el gist para que contribuyas si quieres.
https://gist.github.com/capynet/c7aa09a996fe909a0960

NOTA: En algunas instalaciones de monit, hay que tocar su archivo de configuración general para que incluya los archvos de monitorización que añadamos. El archivo es /etc/monit/monitrc y tienes que editarlo como sudo y añadir al final “include/etc/monit/monitrc.d/*” si no lo tuviera ya puesto.

Bueno si a estas alturas todavía no tienes instalado forever, instalalo con sudo npm install forever -g

Hemos acabado, ya puedes arrancar monit o reiniciarlo si ya estaba corriendo. Monit va a usar el script que creamos para el para ver si el servicio está corriendo, si no es así, el solito se encarga de levantarlo y mantenerlo en funcionamiento inclusive después de reiniciar el servidor.

Chau!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>