Oct 122014
 

Article di Mikko Ohtamaa già pubblicato sul suo blog

Spesso si vuole automatizzare qualcosa usando scripting di shell. In un mondo perfetto il vostro script funziona senza problemi, senza stancarsi, senza errori, e ci si può sedere nella vostra scrivania e sorseggiare un caffè.

31451391

Poi entriamo nel mondo reale: La rete è scollegata. Il DNS va male. I vostri hook HTTP e download vanno in stallo. La comunicazione tra processi si blocca. Effettivamente questo significa che, anche se lo script viene eseguito correttamente dal punto di sistema operativo questo non finirà il suo lavoro prima che voi terminiate la vostra tazza di caffè.




Di seguito è riportato un esempio di come creare timeout e notifiche in uno script di shell.

1. Never gonna give you up

(c) Rick Astley

L’automazione deve funzionare al 100% e si deve sempre sapere se non lo fa. In caso contrario, se non ci si può fidare dei sistemi automatizzati si potrebbe avere questo momento glorioso di “oh, è rotto da tre mesi”. Nessuna quantità di caffè rende il vostro giorno migliore dopo questo. Poi si trascorrono le vostre serate a riflettere se il vostro script è in esecuzione invece di giocare a Borderlands 2.

Alcune guardie di sicurezza per proteggere la vostra tazza di caffè includono

  • Soglie di timeout per i comandi per evitare che le situazioni rimangano in stallo. Es La vostra automazione “fare smallapp” probabilmente non dovrebbe funzionare per 50 ore di fila.
  • Ricevere una notifica se un processo completamente automatizzato non finisce come previsto. In modo che si scopra il problema subito, non tre mesi dopo. Non utilizzare la posta elettronica come canale di comunicazione, è inaffidabile ed ha un terribile rapporto segnale-rumore. Le soluzioni migliori sono di messaggistica istantanea (Skype), SMS (guardate twilio.com)
  • Ricevere una notifica anche quando un servizio, che dovrebbe essere in esecuzione tutto il tempo, si riavvia.

2. Timeout.bash

Lo scripting in shell (sh, zsh, bash) non offre strumenti integrati per il timeouting dei comandi di default (per favore correggetemi se sbaglio, ma non ho trovato nulla anche consultando stackoverflow.com ). Nel libro di Bash cookbook, esiste un esempio di timeout wrapper script (The orignal SO.com answer).

Il trucco è che quando il wrapper timeout termina il comando, si darà il codice di uscita di SIGTERM (143) o SIGKILL (137) allo script padre. Questo potrebbe non essere del tutto chiaro dalla lettura dello script.

 

3 Utilizzare un wrapper per il timeout ed inviare le notifiche di errore a Skype

Di seguito è riportato un esempio di come è possibile collegare un timeout al proprio script. Qui abbiamo uno script semplice di continous integration ( ghetto-ci ), che verifica un repository di controllo delle revisioni ed a ogni cambiamento esegue una suite di test. Un fallimento del test è riferito a Skype da ghetto-ci con Sevabot Skype bot . Lo script utilizza un modo specifico del server (Ubuntu) per impostare un server X headless, in modo che i test possano essere eseguiti da Firefox sul server. Il ciclo continuo di integrazione viene distribuito semplicemente lasciando in esecuzione sul terminale in modalità screen sul server.

Alcune Protezioni presenti: Lo script deve effettuare controlli supplementari per la protezione contro processi appesi da uccidendoli utilizzando pkill prima dell’inizio di ogni prova. Il WebDriver di Selenium sembra causare spesso situazioni in cui le prove di Python non escono in modo pulito, lasciando spesso vari tipi di processi zombie. In questo caso, il comando test va in timeout utilizzando il wrapper timeout e otteniamo una notifica su Skype. Sulla base di questo siamo in grado di perfezionare la logica dei test in esecuzione, il ritardo di timeout in modo da rendere lo script più robusto e permetterci di concentrarci di più sul bere il caffè e meno sul guardare un processo in esecuzione in loop in una schermata UNIX per verificare potenziali guasti.

Perdonatemi per l’eventuale brutto codice di script di shell. SH non è il mio linguaggio principale. Il codice di esempio è anche su Github.

#!/bin/bash
#
# Run CI check for every 5 minutes and
# execute tests if svn has been updated.
#
# The script sets up xvfb (X window framebuffer)
# which is used to run the headless Firefox.
#
# We will post a Skype message if the Selenium WebDriver
# has some issues (it often hangs)
#
# We also signal the tests to use a special static Firefox build
# and do not rely (auto-updated) system Firefox
#
# NOTE: This script is NOT sh compliant (echo -n),
# bash needed
 
# Timeouting commands shell script helper
# http://stackoverflow.com/a/687994/315168
TIMEOUT=timeout.sh
 
# Which FF binary we use to run the tests
FIXED_FIREFOX=$HOME/ff16/firefox/firefox
 
# It's me, Mariooo!
SELF=$(readlink -f "$0")
 
# Skype endpoint information
SKYPE_CHAT_ID="1234567890"
 
SKYPE_SHARED_SECRET="toholampi"
 
SEVABOT_SERVER="http://yourserver.com:5000/msg/"
 
#
#  Helper function to send Skype messages from help scripts.
#  The messages are signed with a shared seceret.
#
#  Parameter 1 is the message
#
function send_skype_message() {
    msg="$1"
    md5=`echo -n "$SKYPE_CHAT_ID$msg$SKYPE_SHARED_SECRET" | md5sum`
 
    #md5sum pads a '-' to the end of the string. We need to get rid of that.
    for m in $md5; do
        break
    done
 
    result=`curl --silent --data-urlencode chat="$SKYPE_CHAT_ID" --data-urlencode msg="$msg" --data-urlencode md5="$m" $SEVABOT_SERVER`
    if [ "$result" != "OK" ] ; then
        echo "Error in HTTP communicating to Sevabot: $result"
    fi
}
 
# Tell the tests to use downgraded FF!6
# which actually works with Selenium
if [ -e $FIXED_FIREFOX ] ; then
    FIREFOX_PATH=$FIREFOX_PATH
    export FIREFOX_PATH
    echo "Using static Firefox 16 build to run the tests"
fi
 
send_skype_message "♫ ci-loop.sh restarted at $SELF"
 
while true
do
    # Kill hung testing processes (it might happen)
    pkill -f "bin/test"
 
    # Purge existing xvfb just in case
    pkill Xvfb
 
    sleep 5
 
    echo "Opening virtual X11"
 
    # Start headless X
    Xvfb :15 -ac -screen 0 1024x768x24 &
 
    # Tell FF to use this X server
    export DISPLAY=localhost:15.0
 
    # Run one cycle of continous integration,
    # give it 15 minutes to finish
    echo "Starting test run"
    $TIMEOUT -t 900 continous-integration.sh
    result=$?
 
    if [ "$result" == "143" ] ; then
        echo "------- CI TIMEOUT OOPS --------"
        send_skype_message "⚡ Continuous integration tests timed out - check the ci-loop.sh screen for problems"
    fi
 
    sleep 300
done


Popular Posts:

Flattr this!

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

*