pas le getopts de bash; il faut encore un peu bricoler derrière.
Vérifier que l'environnement est correctement configuré.
Parfois certains script ont besoins d'utiliser des variables d'environnements pour effectuer certaines actions.
En début de script, placer ce genre de ligne évite d'avoir un script qui s'execute à moitié avant de planter et laisser le systeme dans un etat bancal.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 echo ${MAVAR:?} > /dev/null
Merci Ripat pour l'info. J'avais quelque chose que je mets ici, des fois que cela intéresse quelqu'un...
Certains scripts d'admin ne doivent pas être exécutés plusieurs fois en parallèle. Il est peu probable que deux admins fassent tourner ces scripts en même temps, mais si cela arrivait, ce serait vraiment gênant. Alors voici ce que j'ai écrit.
Les points intéressants sont:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #!/bin/bash # init execName=$(basename $0) lockFile="/tmp/$execName.pid" # check lock if [[ -f $lockFile ]] then isRunning=$(ps -ef | awk -v p=$(cat $lockFile) -v e=$execName '$2 == p && $NF ~ e {print "true"}') if [[ $isRunning == "true" ]] then owner=$(ls -l $lockFile | awk '{print $3}') ago=$(ls -l --time-style=+%s $lockFile | awk -v f=$lockFile '$NF == f {print systime() - $6}') echo "ERROR: $execName already started $ago sec ago by $owner. Nothing done, exiting..." exit 1 else rm $lockFile fi fi # set lock echo $$ > $lockFile chmod 666 $lockFile # script ... # end rm $lockFile
- On sait si le script est en train de tourner.
- On sait qui l'a lancé.
- On sait il y a combien de temps.
- Si le script est mal sorti et n'a pas nettoyé son fichier, c'est fait automatiquement.
Si vous avez des idées sur ce bout de code (intérêt, optimisation), je suis toute ouïe.
C'est dans l'idée de lockfile qui, lui aussi, peut nettoyer le sémaphore après un certain délai (option locktimeout). Ton script le fait si plus aucun processus n'utilise le sémaphore. C'est pas plus mal.
Voici ta version, optimisée et débarrassée des bashismes:
Optimisation porte sur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 # init lockFile="/tmp/${0##*/}.pid" # check lock if [ -f $lockFile ] && . $lockFile && ps -p $PID >/dev/null && [ "$PROG" = "${0##*/}" ]; then echo "ERROR: $PROG already started at $TIME by $OWNER on $TTY. Nothing done, exiting..." exit 1 fi # set lock ps -p $$ --no-header -o user,pid,comm,stime,tty | awk '{printf "OWNER=%s;PID=%s;PROG=%s;TIME=%s;TTY=%s",$1,$2,$3,$4,$5}' > $lockFile chmod 666 $lockFile # script ... # end rm -f $lockFile exit 0
- suppressions des programmes extérieurs inutiles (basename, cat, awk, ls etc...)
- suppression d'un rm inutile puisque le ficher sémaphore est écrasé plus bas.
- ajout d'un exit 0 pour sortir proprement (bonne habitude si on chaîne des scripts)
Bashisme: Ubuntu, Debian et toute la famille UNIX poussent à l'utilisation de scripts POSIX pour des raisons de portabilité. Quand il est possible de se passer des bashismes, autant le faire. Le seul bashisme que j'ai trouvé est la structure [[ $a == $b ]]. Si, par contre, ton script a besoin des tableaux et autres facilités des shell plus "riches" comme bash, ksh et zsh, rien ne t'empêchera d'utiliser la partie sémaphore POSIX.
A voir...
Merci Ripat de partager de ton expérience.
- OK pour le Bashisme.
- Optimisation très intéressante, notamment de sourcer le fichier pour obtenir les informations plutôt que de les chercher tant bien que mal. Mon utilisation de ps était très rudimentaire!
- C'est vrai qu'il est inutile de supprimer le fichier de lock.
Je vais de ce pas modifier mes scripts... Enfin j'attendrai lundi quand même!
Bonjour,
ou plus simplement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part : ${MAVAR:?}
![]()
En créant de multiples scripts, j'ai eu envie des créer de l'aide en ligne, d'afficher leur version, ou de les lancer en version debug, plus certaines particularités pour certains scripts. La commande getops fût la bienvenue. Plusieurs étapes ont vu le jour dans mon idée, dont voici la première :
- mutualisation des options dites « communes » (ex : -h, -x) en les incluant dans un script de style bibliothèque.
Mutualisation des options :
Ci-dessous, la commande getops lançant la bibliothèque d'options communes :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 while getopts abcdefghijklmnopqrstivwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ OPTION do case $OPTION in a) f_a_all # traitements (ici lancement de la function f_a_all) ;; *) . /usr/expl/proc/BIBLIOTHEQUES/getopts.lib ;; esac done
La bibliothèque des options communes (getopts.lib) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 case $OPTION in h) help # traitements (ici lancement de la function help) ;; v) version # traitements (ici lancement de la function version) ;; x) set x # traitements (ici set x) ;; *) echo "Erreur : l'option courte \"$OPTION\" est inexistante" exit esac
PS : dans cette exemple, les options a, h, v et x sont reconnues. Les autres options afficheront :
l'option courte \"$OPTION\" est inexistante"
Attention : la bibliothèque doit être lancée avec le point devant « . »
Dans cet exemple, nous pouvons utiliser l'option -x au lieu d'ajouter la commande "set -x" dans le script et évite son modification.
Cela permet une plus grande souplesse dans les ajouts, modifications ou suppressions d'options communes (ex : ajout d'options longues dans ma seconde étape).
Partager