En surfant sur le réseau national, je suis tombé sur un article intéressant (que j'apporte ici textuellement car il est magistralement expliqué) où son auteur nous montre comment rendre nos scripts Bash plus robustes en utilisant Pièges.
Rendez vos scripts bash plus robustes avec des traps
Imaginez que vous ayez un script bash qui s'exécute tous les jours toutes les six heures et qu'à un moment donné, il échoue ou que le même script s'exécute deux fois simultanément. Ces deux situations sont assez inconfortables car elles nécessitent une intervention humaine pour être corrigées ou, à certains moments, elles ne peuvent pas être traitées, laissant le système dans un état incohérent. La solution à cela, entre autres, consiste à utiliser des pièges.
Traps est un moyen simple et efficace de contrôler la sortie des scripts bash. Revenons à la même situation initiale, si le script est arrêté manuellement, par exemple avec ctrl-c, il est interrompu renvoyant le signal de sortie
INT
et s'il se termine par
kill
alors la sortie serait
TERM
.
Tous les codes de sortie possibles peuvent être visualisés avec
kill -l
Cependant, les plus utilisés sont précisément
INT, TERME, SORTIE
Si le script consiste, par exemple, à synchroniser des fichiers avec
rsync
la chose la plus sensée est de s'appuyer sur un fichier de verrouillage qui ne permet pas au script de s'exécuter simultanément:
LOCK = "/ var / run / rsync.lock" si [! -e $ LOCK]; puis touchez $ LOCK rsync -avz foo bar rm $ LOCK sinon echo "rsync est déjà en cours d'exécution" fi
En espagnol ordinaire, le script ci-dessus vérifie si le fichier de verrouillage existe et s'il n'existe pas, il le crée et exécute plus tard la commande correspondante, supprimant finalement le fichier de verrouillage. Si le fichier existe, le script envoie simplement un message à l'utilisateur indiquant que la commande est déjà en cours d'exécution.
Cependant, lorsqu'il y a une situation problématique, il peut arriver que le fichier de verrouillage ne soit pas éliminé, ruinant les effets indésirables. La solution est très simple:
LOCK = "/ var / run / rsync.lock" si [! -e $ LOCK]; then trap "rm -f $ LOCK; exit" INT TERM EXIT touch $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM EXIT else echo "rsync est déjà en cours d'exécution" fi
La particularité de cette solution est que la commande est enfermée dans un piège, de sorte que lorsqu'un signal est reçu
INT, TERME, SORTIE
le script s'arrête et efface le fichier de verrouillage.
Cela vaut la peine de dire qu'il pourrait y avoir une situation de concurrence dans le script ci-dessus entre le moment où le fichier de verrouillage est vérifié et le moment où il est créé. Une solution possible serait d'utiliser une redirection et le mode noclobber de bash qui ne redirige pas vers un fichier existant:
LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; puis trap 'rm -f "$ LOCK"; exit $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT else echo "rsync est déjà en cours d'exécution: $ (cat $ LCK)" fi
La particularité de ce dernier est qu'il est utilisé comme je l'avais déjà dit, le mode noclobber et que le fichier de verrouillage contient le PID du processus en cours d'exécution.
Il convient également de mentionner qu'il existe d'autres solutions telles que
flock
o
solo
Cependant, dans cet article, je voulais partager les solutions avec les propres ressources de bash. Vous pouvez en apprendre un peu plus sur les pièges avec ce excellent guide.
Brillant! Merci d'avoir partagé.
Bel article, il suffit de changer 'echo "rsync est déjà en cours d'exécution: $ (cat $ LCK)"' en 'echo "rsync est déjà en cours d'exécution: $ (cat $ LOCK)"'
salutations
Un article très intéressant, oui monsieur! C'est ce que je garde.
C'est une commande très utile à garder à l'esprit. Je l'ai utilisé dans un script que j'ai publié dans un article, pour supprimer certains fichiers que le script a créés lors de son arrêt.
Très intéressant, oui monsieur.