Come già affermato in questo post, nodejs ha rappresentato una vera e propria rivoluzione nella programmazione Web, in quanto ha consentito ad un linguaggio nativamente client-side come javascrip, di essere riadattato ed utilizzato come linguaggio server-side.
Il funzionamento del suddetto applicativo è abbastanza banale: si richiama il binario da CLI e gli si da in pasto il file di configurazione del “server javascrip”, ad esempio:
[root@linuxbox ~]# node server.js
Per lasciarlo attivo in background occorre utilizzare un tool apposito come screen oppure un semplice nohup:
[root@linuxbox ~]# nohup node server.js
Va da se che tale soluzione per “demonizzare” nodejs non è proprio pulitissima ed è per questa ragione che ho deciso di creare un demone ad hoc per il suddetto applicativo:
#!/bin/bash # chkconfig: 2345 95 20 # description: nodejs service # processname: nodejs . /etc/rc.d/init.d/functions USER="node" DAEMON="/usr/bin/node" ROOT_DIR="/home/nodejs" SERVER="$ROOT_DIR/server.js" for i in {1..8} do do_start() { PORT="900$i" LOG_FILE="$ROOT_DIR/server$i.js.log" result=`ps aux | grep "server.js $PORT" | grep -v grep` if [ -z "$result" ] ; then echo -n $"Starting $SERVER $i: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT >> $LOG_FILE &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER $i already started." RETVAL=1 fi } do_status() { PORT="900$i" result=`ps aux | grep "server.js $PORT" | grep -v grep` if [ -n "$result" ] ; then echo "$SERVER $i is started." RETVAL=0 else echo "$SERVER $i is stopped." RETVAL=1 fi } done do_stop() { echo -n $"Stopping $SERVER:" killall -w node RETVAL=$? echo [ $RETVAL -eq 0 ] } case "$1" in start) for i in {1..8} do do_start done ;; stop) do_stop ;; status) for i in {1..8} do do_status done ;; restart) do_stop for i in {1..8} do do_start done ;; *) echo "Usage: $0 {start|stop|status|restart}" RETVAL=1 esac exit $RETVAL
Tale demone, ad ogni avvio, esegue 8 istanze di nodejs, ciascuna delle quali è in ascolto su una porta dedicata (dalla 9001 alla 9008). Per non definire 8 funzioni do_start() e do_status() ho utilizzato un banale ciclo for e poichè la funzione do_stop() effettua un kill di tutti i processi il cui nome contiente la stringa “node” (killall -w), essa è stata estromessa dal predetto loop.
Inoltre, per ragioni di sicurezza, è stato definito un utente dedicato per l’esecuzione dell’applicativo (USER=”node”), la cui root directory è la propria home (ROOT_DIR=”/home/nodejs/), mentre il file di configurazione di nodejs è specificato all’interno della variabile SERVER (SERVER=”$ROOT_DIR/server.js”).
Infine, all’interno della funzione do_start(), ho definito il file di log per ciascuna istanza di nodejs, utilizzando la direttiva LOG_FILE=”$ROOT_DIR/server$i.js.log”.
Per completezza, di seguito riporto anche la versione senza cicli for:
#!/bin/bash # chkconfig: 2345 95 20 # description: nodejs service # processname: nodejs . /etc/rc.d/init.d/functions USER="node" DAEMON="/usr/bin/node" ROOT_DIR="/home/nodejs/" SERVER="$ROOT_DIR/server.js" PORT1="9001" PORT2="9002" PORT3="9003" PORT4="9004" PORT5="9005" PORT6="9006" PORT7="9007" PORT8="9008" LOG_FILE1="$ROOT_DIR/server1.js.log" LOG_FILE2="$ROOT_DIR/server2.js.log" LOG_FILE3="$ROOT_DIR/server3.js.log" LOG_FILE4="$ROOT_DIR/server4.js.log" LOG_FILE5="$ROOT_DIR/server5.js.log" LOG_FILE6="$ROOT_DIR/server6.js.log" LOG_FILE7="$ROOT_DIR/server7.js.log" LOG_FILE8="$ROOT_DIR/server8.js.log" do_start1() { result1=`ps aux | grep "server.js $PORT1" | grep -v grep` if [ -z "$result1" ] ; then echo -n $"Starting $SERVER 1: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT1 >> $LOG_FILE1 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 1 already started." RETVAL=1 fi } do_start2() { result2=`ps aux | grep "server.js $PORT2" | grep -v grep` if [ -z "$result2" ] ; then echo -n $"Starting $SERVER 2: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT2 >> $LOG_FILE2 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 2 already started." RETVAL=1 fi } do_start3() { result3=`ps aux | grep "server.js $PORT3" | grep -v grep` if [ -z "$result3" ] ; then echo -n $"Starting $SERVER 3: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT3 >> $LOG_FILE3 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 3 already started." RETVAL=1 fi } do_start4() { result4=`ps aux | grep "server.js $PORT4" | grep -v grep` if [ -z "$result4" ] ; then echo -n $"Starting $SERVER 4: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT4 >> $LOG_FILE4 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 4 already started." RETVAL=1 fi } do_start5() { result5=`ps aux | grep "server.js $PORT5" | grep -v grep` if [ -z "$result5" ] ; then echo -n $"Starting $SERVER 5: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT5 >> $LOG_FILE5 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 5 already started." RETVAL=1 fi } do_start6() { result6=`ps aux | grep "server.js $PORT6" | grep -v grep` if [ -z "$result6" ] ; then echo -n $"Starting $SERVER 6: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT6 >> $LOG_FILE6 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 6 already started." RETVAL=1 fi } do_start7() { result7=`ps aux | grep "server.js $PORT7" | grep -v grep` if [ -z "$result7" ] ; then echo -n $"Starting $SERVER 7: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT7 >> $LOG_FILE7 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 7 already started." RETVAL=1 fi } do_start8() { result8=`ps aux | grep "server.js $PORT8" | grep -v grep` if [ -z "$result8" ] ; then echo -n $"Starting $SERVER 8: " runuser -l "$USER" -c "$DAEMON $SERVER $PORT8 >> $LOG_FILE8 &" && echo_success || echo_failure RETVAL=$? echo [ $RETVAL -eq 0 ] else echo "$SERVER 8 already started." RETVAL=1 fi } do_status1() { result1=`ps aux | grep "server.js $PORT1" | grep -v grep` if [ -n "$result1" ] ; then echo "$SERVER 1 is started." RETVAL=0 else echo "$SERVER 1 is stopped." RETVAL=1 fi } do_status2() { result2=`ps aux | grep "server.js $PORT2" | grep -v grep` if [ -n "$result2" ] ; then echo "$SERVER 2 is started." RETVAL=0 else echo "$SERVER 2 is stopped." RETVAL=1 fi } do_status3() { result3=`ps aux | grep "server.js $PORT3" | grep -v grep` if [ -n "$result3" ] ; then echo "$SERVER 3 is started." RETVAL=0 else echo "$SERVER 3 is stopped." RETVAL=1 fi } do_status4() { result4=`ps aux | grep "server.js $PORT4" | grep -v grep` if [ -n "$result4" ] ; then echo "$SERVER 4 is started." RETVAL=0 else echo "$SERVER 4 is stopped." RETVAL=1 fi } do_status5() { result5=`ps aux | grep "server.js $PORT5" | grep -v grep` if [ -n "$result5" ] ; then echo "$SERVER 5 is started." RETVAL=0 else echo "$SERVER 5 is stopped." RETVAL=1 fi } do_status6() { result6=`ps aux | grep "server.js $PORT6" | grep -v grep` if [ -n "$result6" ] ; then echo "$SERVER 6 is started." RETVAL=0 else echo "$SERVER 6 is stopped." RETVAL=1 fi } do_status7() { result7=`ps aux | grep "server.js $PORT7" | grep -v grep` if [ -n "$result7" ] ; then echo "$SERVER 7 is started." RETVAL=0 else echo "$SERVER 7 is stopped." RETVAL=1 fi } do_status8() { result8=`ps aux | grep "server.js $PORT8" | grep -v grep` if [ -n "$result8" ] ; then echo "$SERVER 8 is started." RETVAL=0 else echo "$SERVER 8 is stopped." RETVAL=1 fi } do_stop() { echo -n $"Stopping $SERVER:" killall -w node RETVAL=$? echo [ $RETVAL -eq 0 ] } case "$1" in start) do_start1 do_start2 do_start3 do_start4 do_start5 do_start6 do_start7 do_start8 ;; stop) do_stop ;; status) do_status1 do_status2 do_status3 do_status4 do_status5 do_status6 do_status7 do_status8 ;; restart) do_stop do_start1 do_start2 do_start3 do_start4 do_start5 do_start6 do_start7 do_start8 ;; *) echo "Usage: $0 {start|stop|status|restart}" RETVAL=1 esac exit $RETVAL
Basta dare una semplice occhiata e vi renderete subito conto del perchè abbia preferito la prima versione a quest’ultima.
Non ci rimane che rendere il demone eseguibile:
[root@linuxbox ~]# chmod +x nodejs
spostarlo nella directory /etc/init.d:
[root@linuxbox ~]# mv nodejs /etc/init.d
ed avviarlo:
[root@linuxbox ~]# service nodejs start
E’ tutto.