Navigando nella rete nazionale mi sono imbattuto in un file articolo interessante (che porto qui testualmente perché è magistralmente spiegato) dove il suo autore ci mostra come rendere i nostri script bash più robusti usando Trappole.
Rendi i tuoi script bash più robusti con le trappole
Immagina di avere uno script bash che viene eseguito ogni giorno ogni sei ore e che a un certo punto fallisce o che lo stesso script viene eseguito due volte contemporaneamente. Queste due situazioni sono abbastanza scomode poiché richiedono l'intervento umano per essere corrette o in determinati momenti non possono essere affrontate, lasciando il sistema in uno stato incoerente. La soluzione a questo, tra l'altro, è usare le trappole.
Traps è un modo semplice ed efficace per controllare l'output degli script bash. Torniamo alla stessa situazione iniziale, se lo script viene fermato manualmente, ad esempio con ctrl-c, viene interrotto restituendo il segnale in uscita
INT
e se finisce con
kill
allora l'output sarebbe
TERM
.
Tutti i possibili codici di uscita possono essere visualizzati con
kill -l
tuttavia le più utilizzate sono appunto
INT, TERMINE, USCITA
Se lo script consiste, ad esempio, nella sincronizzazione dei file con
rsync
la cosa più sensata è fare affidamento su un file di blocco che non consente l'esecuzione simultanea dello script:
LOCK = "/ var / run / rsync.lock" se [! -e $ LOCK]; quindi tocca $ LOCK rsync -avz foo bar rm $ LOCK altrimenti echo "rsync è già in esecuzione" fi
In semplice spagnolo, lo script precedente controlla se il file di blocco esiste e se non esiste, lo crea e successivamente esegue il comando corrispondente, eliminando infine il file di blocco. Se il file esiste, lo script invia semplicemente un messaggio all'utente indicando che il comando è già in esecuzione.
Tuttavia, quando si verifica una situazione problematica può accadere che il file di blocco non venga eliminato, rovinando gli effetti indesiderati. La soluzione è molto semplice:
LOCK = "/ var / run / rsync.lock" se [! -e $ LOCK]; quindi trap "rm -f $ LOCK; exit" INT TERM EXIT tocca $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM EXIT else echo "rsync è già in esecuzione" fi
La particolarità di questa soluzione è che il comando è racchiuso in una trappola, in modo che quando si riceve un segnale
INT, TERMINE, USCITA
lo script si ferma e cancella il file di blocco.
Vale la pena dire che potrebbe esserci una situazione di concorrenza nello script sopra tra il momento in cui il file di blocco viene verificato e il momento in cui viene creato. Una possibile soluzione sarebbe quella di utilizzare un reindirizzamento e la modalità noclobber di bash che non reindirizza a un file esistente:
LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; quindi trap 'rm -f "$ LOCK"; exit $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT else echo "rsync è già in esecuzione: $ (cat $ LCK)" fi
La particolarità di quest'ultima è che viene utilizzata, come avevo già detto, la modalità noclobber e che il file di lock contiene il PID del processo che si sta eseguendo.
Vale anche la pena ricordare che esistono altre soluzioni come
flock
o
solo
tuttavia in questo post ho voluto condividere le soluzioni con le risorse proprie di bash. Puoi imparare un po 'di più sulle trappole con questo ottima guida.
Grande! Grazie per la condivisione.
Bell'articolo, cambia solo 'echo "rsync è già in esecuzione: $ (cat $ LCK)"' in 'echo "rsync è già in esecuzione: $ (cat $ LOCK)"'
saluti
Un articolo molto interessante, sissignore! Questo lo tengo.
È un comando molto utile da tenere a mente. L'ho usato in uno script che ho pubblicato in un post, per eliminare alcuni file che lo script ha creato quando è stato interrotto.
Molto interessante, sissignore.