www.errorediridondanzaciclicodotcom

  • Home
  • Script restart
  • BACK P.P.
  • Riavviare in automatico script

    A volte si ha un programma o uno script che è sempre in running (es per mostrare una dashboard via html) e che per ragioni non identificate tende a bloccarsi e cadere.
    Ho preparato un sistema basato su crontab e bash per fare un controllo se il programma è in running e, se non attivo, fare il restart.
    Attenzione però che il mio caso è quello di un programma o uno script, non quello di un processo, forse più semplice da gestire.

    Qui di seguito il file bash che esegue il check:

    #!/bin/bash
    pgrep -f 'vostro_script.py' >/dev/null
    if [ $? -ne 0 ] ; then
       echo "stopped $(date)" >> ./stops.txt
       sudo /sbin/shutdown -r now
    fi

    Partiamo dall'inizio: solito shebang per il lancio da riga di comando.

    Si passa poi alla verifica dello script se è in running. Nel mio caso si tratta di uno script in python. Con il normale pidof, ad esempio, si può mettere come argomento "python3" e il check restituirà il numero di pid di python3. Si tratta però di un processo (es. python), non di uno script.
    Per cercare se uno script specifico è in running si deve usare l'istruzione pgrep -f che restituirà il pid specifico relativo. Infatti se ci fossero 2 script di python in running, con pidof non si potrebbe sapere a quale script appartiene uno dei due numeri.

    A questo punto abbiamo il numero di pid e, quindi, facciamo il check. Questo check, in realtà non è sul numero di pid ma sul flag dell'exit status del check. Ciò si ottiene con l'istruzione "$?". In pratica la condizione dice:

    se l'exit status del comando precedente è diverso da 0 ...... then

    (nel nostro caso è 1 ma potrebbe essere in pgrep anche 2 o 3).
    Infatti l'exit flag del comando pgrep è 0 se il programma ha un numero di pid (cioè è running), è 1 se invece non è presente tra i processi.

    Quindi, se l'exit status non è uguale a 0 (lo script non è in running) allora prima stamperò, su un file che mi serve da log, la parola "stopped" seguita dalla data/ora in cui è successo.
    Subito dopo posso dare il comando di restart del processo.

    Nel mio script vedete però che ho fatto un riavvio: il motivo è legato a VNC per il Raspberry OS a 64bit. Questo OS non ha il classico VNC installato perche non è compatibile con i 64bit, ho dovuto quindi installare "TightVNC".
    Il mio Raspi non ha monitor ma accedo in GUI solo tramite VNC. Quando provo a fare il restart dello script che si è fermato, mi dà errore di display perchè questo script lancia una finestra di pygame. Per partire, pygame, deve essere inizializzato ma, se ciò viene fatto successivamente all'inizializzazione di partenza, trova che il display 0:0 è già usato. Senza scervellarmi più di tanto, faccio un reboot e morta lì!

    Questo script deve poi essere messo in crontab. Faccio partire lo script ogni minuto e, se il pitone è caduto, riavvia il tutto.

    Una nota: se, al posto di mettere una parentesi quadra, avessi messo la doppia parentesi le cose si sarebbero complicate un pochetto.
    La doppia parentesi quadra è utilizzata nelle condizionali, a volte, perchè permette qualche passaggio in meno o qualche funzione in più. Si tratta di una sintassi utilizzata da bash (e altre due shell) che però non è compatibile con sh.
    Mettiamo di avere la doppia parentesi nel nostro script e avere scritto nello shebang /bin/bash. Se proviamo a lanciare lo script come ./mio_script.sh sul terminale funziona tutto (come scritto nello shebang abbiamo dato priorità a bash). Se mettiamo lo stesso comando in crontab, non partirà. Il motivo è che crontab utilizza di default sh che non riconosce la doppia parentesi. Per farlo funzionare bisogna specificare in crontab di usare bash.
    Nel mio caso, con una condizione di "-ne" l'uso con singola (sh) o doppia (bash) parentesi quadra non cambia e non è necessario per questa istruzione.