Riavvio dei servizi? Automatico è meglio!
E' inutile negarlo! I processi in esecuzione su un server prima o poi si interrompono inaspettatamente. La questione non è quindi SE ma nemmeno QUANDO: la vera questione è COSA fare in una situazione di discontinuità di servizio.
Le questioni legate al disaster recovery non sono però assolute ma vanno correlate all'effettiva necessità di ripristino dei servizi di un sistema in un certo intervallo di tempo.
Vi sono sistemi per la cui criticità, il costo della discontinuità di servizio anche per un breve intervallo di tempo (ad esempio nell'ordine dei minuti) è molto alto, altri sistemi dove è invece tollerabile un'interruzione di servizio misurabile in giorni.
Strategie ed architetture differenti vengono quindi impostate in funzione del livello di criticità del sistema ma nella maggioranza dei casi è sempre bene prevedere il re-start automatico di un servizio che si interrompe inaspettatamente.
Le interruzioni inaspettate di un processo avvengono per una pluralità di motivi che dipendono generalmente da uno stato del sistema imprevisto dal software. Il "programma" non è quindi in grado di gestire l'eccezione (letteralmente "exception") e si interrompe.
Immaginiamo l'impatto di un'interruzione del daemon di un web server o di un database... a meno di una gestione distribuita dei servizi (cloud, bilanciamento di carico...) l'utente troverà una sconfortante schermata del tipo:
In casi come questo, di interruzione inattesa di un daemon, è auspicabile un riavvio automatico, con notifica via mail del riavvio automatico al system admin per la successiva analisi dei log in modo da indentificare la causa scatenante del problema.
Il riavvio automatico è quindi una procedura di emergenza, mette al riparo da lunghe interruzioni di servizio le cui cause vanno comunque investigate e risolte.
La logica che seguiremo è quella di:
- programmare uno script che monitori i processi del server che ci interessano, verificando che siano in esecuzione;
- impostare uno scheduler che lanci periodicamente lo script di monitoring.
L'ipotesi di lavoro è quella in ambiente GNU/Linux (nello specifico negli esempi mi riferirò ad una distribuzione Debian).
Per monitorare i processi utilizzeremo pgrep che restituisce il pid (process id) che identifica univocamente il processo in esecuzione sul server: qualora pgrep non restituisca alcun id del processo, il processo non sarà in esecuzione (e quindi andrà riavviato).
I daemon che sorveglieremo sono quelli classici di un'installazione LAMP ovvero: web server Apache, MySQL server e PHP.
Lo script invoca pgrep sui daemon launcher di apache, mysql e php.
Il codice dello script bash restartDaemon.sh è il seguente:
#!/bin/bash PGREP="/usr/bin/pgrep" # Restart apache2 daemon RESTART="/etc/init.d/apache2 restart" HTTPD="apache2" $PGREP ${HTTPD} if [ $? -ne 0 ] then $RESTART fi # Restart php5-fpm daemon RESTARTPHP="/etc/init.d/php5-fpm restart" PHP5="php5-fpm" $PGREP ${PHP5} if [ $? -ne 0 ] then $RESTARTPHP fi # Restart mysql daemon RESTARTMYSQL="/etc/init.d/mysql restart" MYSQL="mysqld" $PGREP ${MYSQL} if [ $? -ne 0 ] then $RESTARTMYSQL fi
Lo script restartDaemon.sh dovrà avere permessi di esecuzione, ad esempio:
chdmod 755 restartDaemon.sh
Una volta che lo script di restart sia stato impostato, occorrerà richiamarlo periodicamente: il candidato perfetto per questo ruolo è crontab.
crond è il daemon di crontab e viene eseguito ogni 60 secondi. Il suo compito è di lanciare i comandi specificati in crontab all'orario indicato
Per avere l'elenco dei cronjob attivi in crontab, da terminale dare il comando:
crontab -l
Crontab restituisce una schermata del tipo seguente:
Come si vede, sul server di esempio viene invocato restartDaemon.sh ogni minuto ed una procedura automatica di backup ogni giorno alle 5:30 del mattino.
Nel nostro esempio l'esecuzione di restartDaemon.sh è già impostata su crontab ma come abbiamo fatto per inserirla? È sufficiente indicare a crontab che vogliamo entrare in modalità editing lanciandolo mediante:
crontab -e
Una volta che crontab sia in esecuzione, premere il tasto "a" e posizionare il cursore sulle ultime righe in modo da aggiungere la chiamata a restartDaemon.sh.
La sintassi utilizzata in crontab per indicare la periodicità è:
minuti [0 - 59], ore [0, 23], giorni (del mese, intervallo [1-31] ), mese [1-12], giorno (della settimana [0-6])
Il carattere "*" utilizzato per restartDaemon.sh indica qualsiasi valore, quindi * * * * * determina il lancio di restartDaemon.sh ogni minuto di ogni ora di ogni giorno di ogni mese in qualsiasi giorno della settimana... quindi ogni minuto :)
Vi sono anche altri caratteri speciali oltre l'asterisco e precisamente:
- la virgola "," che indica una lista di valori, ad es.: 30 5,6 * * * lancia il processo alle 5:30 ed alle 6:30 ogni giorno.
- il trattino "-" che indica un intervallo di valori, ad es. 30 5-7 * * * lancia il processo alle 5:30, alle 6:30 ed alle 7:30 ogni giorno
- lo slash "/" che indica un incremento dei valori, ad es: */5 5-7 * * * lancia il processo ogni 5 minuti per tutte le ore 5, 6 e 7
Una volta stabilita la periodicità più appropriata (nel nostro caso il monitoring di Apache, MySQL e PHP-FPM avviene ogni 60 secondi), per uscire e salvare il cronjob, premere il tasto ESC e digitare:
:wq
Si uscirà da crontab che indicherà di avere inserito nello scheduler lo script.
L'indicazione aggiuntiva
>/dev/null 2>&1
> indica la redirezione dell'output verso un black hole (quindi l'esecuzione dello script non genererà un flusso verso STDOUT (standard output)
2 indica il file handle per lo standard error
1 indica il file handle per lo standard output
Ovvero: l'esecuzione è reindirizzata verso il black hole, ivi compresi eventuali errori ed output dello script che è stato lanciato da crond.
Altra conseguenza è che l'esecuzione del cronjob non produrrà email verso il system administrator. A tal proposito vedremo in un prossimo articolo come integrare al nostro script bash un job in Perl che effettuerà l'invio mail, solo in caso di restart, con allegato stralcio del log del daemon oggetto di interruzione inattesa.
Ricordo ancora che il restart automatico dei servizi è una procedura di emergenza e che la cause del blocco inatteso vanno investigate con accuratezza partendo dall'analisi dei log (solitamente in /var/log) del daemon che ha subito l'interruzione.