Instalación de proceso de inicio para correr servidor Node.js

Visitas: 60  
Tiempo total: 1 días con 0:45:31 hrs  

En esta publicación se muestran los pasos necesarios para instalar un proceso de inicio, con el objetivo de ejecutar un script Node.js que publicara el servidor que hemos creado. A continuación la configuración utilizada:

Sistema operativo: Ubuntu 12.04 LTS
Kernel: 3.11.0-15-generic
Tipo de OS: 32 bit
Servidor: Node.js
Proceso de inicio: Init

Básicamente, funciona de la siguiente manera: Creamos un script que contendrá el código para publicar el servidor Node.js, este script lo colocamos en la carpeta /etc/init.d y lo registramos, de esta manera el proceso init lo llamara dos veces: Cuando el sistema operativo inicia (enviando el parámetro start) y cuando finaliza (enviando el parámetro stop).

Los parámetros start y stop lo envía de la siguiente manera, es similar a si escribimos la ubicación de nuestro script seguido de los parámetros que hemos establecido:

Se llama en los niveles de ejecución 2 3 4 5

/etc/init.d/proceso start

Se llama en los niveles de ejecución 0 1 6

/etc/init.d/proceso stop

Los niveles de ejecución significa en qué casos el proceso debe de llamarse con el parámetro start o stop (Por ejemplo 0 es cuando la maquina entra en estado de apagado, 6 cuando se inicia. Una explicación más a detalle de esto lo encontramos en la wiki de debían.org, mas adelante muestro el enlace). En nuestro script también podemos definir otros parámetros, como ¿Qué es necesario o cuáles son los requisitos necesarios para llamar a nuestro script?.

Instalación de node js

Para instalar node.js se instalan las dependencias:

sudo apt-get install g++ curl libssl-dev apache2-utils
sudo apt-get install git-core

Nos movemos a la carpeta en donde vamos a descargar node.js

cd /home/jose/Documentos

Descargamos node.js y lo instalamos:

git clone git://github.com/ry/node.git
cd node
./configure
make
sudo make install

Aplicación node.js

El código de la aplicación funciona de la siguiente manera:

var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
var filePath = __dirname + request.url;
if (request.url == "/")
filePath = __dirname+'/gradiente.html';

console.log('Peticion iniciada: '+request.url);
console.log('Peticion iniciada: '+filePath);

var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}

path.exists(filePath, function(exists) {

if (exists) {
fs.readFile(filePath, function(error, content) {
if (error) {
response.writeHead(500);
response.end();
}
else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
}
else {
response.writeHead(404);
response.end();
}
});

}).listen(8124,"0.0.0.0");
console.log('El demonio Node.js ha despertado en el puerto 8124');

El objetivo es correr la aplicación Node.js cuando se inicia la maquina, entonces lo que hace este código es llamar al documento HTML llamado gradiente.html, que a su vez llama a documentos externos CSS y Javascript/Jquery, por este motivo realizamos una comparación de las extensiones de los archivos que se solicitan a Node.js, para cambiar su tipo de contenido a text/javascript o text/css.

En el código Node.js es necesario tener en cuenta, las rutas absolutas de los documentos que se solicitan, por ejemplo no será lo mismo el siguiente código (no funciona, rutas relativas):

var filePath = "./" + request.url;
if (request.url == "/")
filePath = '/gradiente.html';

console.log('Peticion iniciada: '+request.url);
console.log('Peticion iniciada: '+filePath);

Que el siguiente (funciona, rutas absolutas):

var filePath = __dirname + request.url;
if (request.url == "/")
filePath = __dirname+'/gradiente.html';

console.log('Peticion iniciada: '+request.url);
console.log('Peticion iniciada: '+filePath);

A continuación el ejemplo, el servidor se ejecuta en la misma carpeta del archivo servidor.js, que es en /home/jose/Documentos/node/www/html/:

codigo relativo funciona

Pero, al subir un directorio, en la ubicación /home/jose/Documentos/node/www/ y ejecutar de nuevo el servidor – no se encontraran correctamente los archivos que solicitaran al servidor Node.js, esto lo observamos en la imagen, el resultado de Firefox en el fondo está en blanco.

codigo relativo no funciona

Lo anterior lo resumimos en: Utilizar rutas absolutas! Porque el script de inicio se llama desde la ubicación /etc/init.d/ y las demás ubicaciones que son utilizadas por el proceso de inicio. Es necesario mencionar la seguridad, debido al acceso de terceras personas a otros documentos de la maquina desde la web, pero en esta publicación (que es una práctica) se limita a iniciar un script Node.js.

Script de inicio

El script de inicio es:

#!/bin/sh

NODE_ENV="production"
PORT="8124"
APP_DIR="/home/jose/Documentos/node/www/html"
NODE_APP="servidor.js"
CONFIG_DIR="$APP_DIR/.."
PID_DIR="$APP_DIR/../pid"
PID_FILE="$PID_DIR/app.pid"
LOG_DIR="$APP_DIR/../log"
LOG_FILE="$LOG_DIR/app.log"
NODE_EXEC="/usr/local/bin/node"

###############
# Inicia y finaliza de ultimo con $all

# description: crea un proceso de inicio para correr un servidor node.js
### BEGIN INIT INFO
# Provides: node
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: /etc/init.d/node-app start|stop
# Description: Crea un proceso de inicio para correr un servidor node.js
### END INIT INFO

###############

pid_file_exists() {
[ -f "$PID_FILE" ]
}

clean_app() {
if pid_file_exists
then
rm -r "$PID_DIR"
rm -r "$LOG_DIR"
fi
}

start_app() {
clean_app
mkdir -p "$PID_DIR"
mkdir -p "$LOG_DIR"

PORT="$PORT" NODE_ENV="$NODE_ENV" NODE_CONFIG_DIR="$CONFIG_DIR" $NODE_EXEC "$APP_DIR/$NODE_APP" 1>"$LOG_FILE" 2>&1 &
echo $! > "$PID_FILE"
}

stop_app() {
PID="$(cat "$PID_FILE")"
kill $PID
clean_app
}

case "$1" in
start)
start_app
echo "El demonio ha sido creado correctamente!"
;;

stop)
stop_app
echo "EL demonio ha sido detenido correctamente!"
;;

*)
echo "Utilizacion: $0 {start|stop}"
exit 1
;;
Esac

Cuenta con las funciones básicas de start y stop, la función start crea las carpetas LOG y PID, log almacena lo que el servidor node.js muestra, y PID almacena el pid del proceso node.js, cuando se llama la función stop se obtiene el pid y se utiliza el comando kill pid. La función clean_app verifica si existe el archivo PID, y por ende las dos carpetas PID y LOG, si existen las elimina.

El código básico base fue gracias al MIT y Github [https://github.com/chovy/node-startup] Para esta publicación, lo edite – para entenderlo – y usar el código necesario para mis fines específicos.

Al inicio del script, observamos la configuración de variables generales, una de las que más interés tiene es:

NODE_EXEC="/usr/local/bin/node"

Que indica la ubicación del comando node necesario para iniciar el servidor Node.js. También observamos la siguiente cabecera, que mas que un comentario es de importancia debido a que se establecen los parámetros para llamar a este script al inicio:

###############
# Inicia y finaliza de ultimo con $all

# description: crea un proceso de inicio para correr un servidor node.js
### BEGIN INIT INFO
# Provides: node
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: /etc/init.d/node-app start|stop
# Description: Crea un proceso de inicio para correr un servidor node.js
### END INIT INFO

###############

Los parámetros Required-Start y Required-Stop indican que es lo necesario, o los requisitos que necesitamos para poder correr el Script que hemos colocado en la ubicación /etc/init.d, podemos encontrar la explicación de todos sus posibles valores ($local_fs, $network, $named, $portmap, $remote_fs, $syslog, $time, $all) en la pagina [https://wiki.debian.org/LSBInitScripts]

Comandos para instalar el script en el inicio del sistema

Instalar script en el inicio del sistema:

#cd Documentos/node/www
#sudo chmod 777 node-app
#sudo cp node-app /etc/init.d/
#sudo update-rc.d node-app defaults

Y se elimina:

#sudo update-rc.d -f node-app remove
#sudo rm /etc/init.d/node-app

Referencias

[https://arenlasysadmin.wordpress.com/2013/05/05/ejecutar-script-arranque-linux/]
[https://arenlasysadmin.wordpress.com/2013/05/05/configurar-runlevel/]
[http://howtonode.org/how-to-install-nodejs]
[http://www.rackspace.com/es/knowledge_center/article/how-do-i-modify-my-hosts-file]
[http://ubuntuforums.org/showthread.php?t=2193763]
[http://ubuntuforums.org/showthread.php?t=1313898]
[http://kvz.io/blog/2009/12/15/run-nodejs-as-a-service-on-ubuntu-karmic/]
[http://technosophos.com/2012/12/17/run-nodejs-apps-low-ports-without-running-root.html]
[https://help.ubuntu.com/community/UbuntuBootupHowto]
[https://github.com/chovy/node-startup/blob/master/init.d/node-app]
[https://wiki.debian.org/LSBInitScripts]
[http://serverfault.com/questions/271824/node-js-is-not-accessible-from-external-ips-on-ubuntu]
[http://ericsowell.com/blog/2011/5/6/serving-static-files-from-node-js]
[http://stackoverflow.com/questions/20641870/how-to-get-current-path-of-the-file-that-run-the-script-in-nodejs]
[http://es.wikipedia.org/wiki/Nivel_de_ejecuci%C3%B3n]


Para recibir boletines de información, por favor escribe tu correo electrónico:

Por favor ingrese un correo electrónico valido.
Registrado correctamente!