Instalación de proceso de inicio para correr servidor Node.js
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/:
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.
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]