Turandot: Gli enigmi sono tre, la morte una! Caleph: No, no! Gli enigmi sono tre, una la vita! | |
Puccini |
Affecter des mots réservés à des noms de variables.
case=value0 # Pose problème. 23skidoo=value1 # Et là-aussi. # Les noms de variables avec un chiffre sont réservés par le shell. # Essayez _23skidoo=value1. Commencer les variables avec un tiret bas est OK. # Néanmoins... n'utiliser que le tiret bas ne fonctionnera pas. _=25 echo $_ # $_ est une variable spéciale initialisée comme étant le # dernier argument de la dernière commande. xyz((!*=value2 # Pose de sévères problèmes. |
Utiliser un tiret ou d'autres caractères réservés dans un nom de variable.
var-1=23 # Utilisez 'var_1' à la place. |
Utiliser le même nom pour une variable et une fonction. Ceci rend le script difficile à comprendre.
fais_quelquechose () { echo "Cette fonction fait quelque chose avec \"$1\"." } fais_quelquechose=fais_quelquechose fais_quelquechose fais_quelquechose # Tout ceci est légal, mais porte à confusion. |
Utiliser des espaces blancs inappropriés (en contraste avec d'autres langages de programmation, Bash peut être assez chatouilleux avec les espaces blancs).
var1 = 23 # 'var1=23' est correct. # Sur la ligne ci-dessus, Bash essaie d'exécuter la commande "var1" # avec les arguments "=" et "23". let c = $a - $b # 'let c=$a-$b' et 'let "c = $a - $b"' sont corrects. if [ $a -le 5] # if [ $a -le 5 ] est correct. # if [ "$a" -le 5 ] est encore mieux. # [[ $a -le 5 ]] fonctionne aussi. |
Supposer que des variables non initialisées (variables avant qu'une valeur leur soit affectée) sont << remplies de zéros >>. Une variable non initialisée a une valeur << null >>, et non pas zéro.
#!/bin/bash echo "variable_non_initialisee = $variable_non_initialisee" # variable_non_initialisee = |
Mixer = et -eq dans un test. Rappelez-vous, = permet la comparaison de variables littérales et -eq d'entiers.
if [ "$a" = 273 ] # $a est-il un entier ou une # chaîne? if [ "$a" -eq 273 ] # Si $a est un entier. # Quelque fois vous pouvez mélanger -eq et = sans conséquences mauvaises. # Néanmoins... a=273.0 # pas un entier. if [ "$a" = 273 ] then echo "La comparaison fonctionne." else echo "La comparison ne fonctionne pas." fi # La comparison ne fonctionne pas. # Pareil avec a=" 273" et a="0273". # De même, problèmes en essayant d'utiliser "-eq" avec des valeurs non entières. if [ "$a" -eq 273.0 ] then echo "a = $a' fi # Echoue avec un message d'erreur. # test.sh: [: 273.0: integer expression expected |
Mélanger les opérateurs de comparaison d'entiers et de chaînes.
#!/bin/bash # bad-op.sh nombre=1 while [ "$nombre" < 5 ] # Mauvais! Devrait être while [ "nombre" -lt 5 ] do echo -n "$nombre " let "nombre += 1" done # En lançant ceci, un message d'erreur : # bad-op.sh: 5: No such file or directory |
Quelque fois, des variables à l'intérieur des crochets de << test >> ([ ]) ont besoin d'être mis entre guillemets (doubles). Ne pas le faire risque de causer un comportement inattendu. Voir Exemple 7-6, Exemple 16-4 et Exemple 9-6.
Les commandes lancées à partir d'un script peuvent échouer parce que le propriétaire d'un script ne possède pas les droits d'exécution. Si un utilisateur ne peut exécuter une commande à partir de la ligne de commande, alors la placer dans un script échouera de la même façon. Essayer de changer les droits de la commande en question, peut-être même en initialisant le bit suid (en tant que root, bien sûr).
Essayer d'utiliser - comme opérateur de redirection (qu'il n'est pas) résultera habituellement en une surprise peu plaisante.
commande1 2> - | commande2 # Essayer de rediriger la # sortie d'erreurs dans un tube... # ...ne fonctionnera pas commande1 2>& - | commande2 # Aussi futile. Merci, S.C. |
Utiliser les fonctionnalités de Bash version 2+ peut poser des soucis avec les messages d'erreur. Les anciennes machines Linux peuvent avoir une version 1.XX de Bash en installation par défaut.
#!/bin/bash minimum_version=2 # Comme Chet Ramey ajoute constamment de nouvelles fonctionnalités à Bash, # vous pourriez configurer $minimum_version à 2.XX, ou quoi que ce soit de plus # approprié. E_MAUVAISE_VERSION=80 if [ "$BASH_VERSION" \< "$minimum_version" ] then echo "Ce script fonctionne seulement avec Bash, version $minimum ou ultérieure." echo "Une mise à jour est fortement recommendée." exit $E_MAUVAISE_VERSION fi ... |
Utiliser les fonctionnalités spécifiques à Bash dans un script shell Bourne (#!/bin/sh) sur une machine non Linux peut causer un comportement inattendu. Un système Linux crée habituellement un alias sh vers bash, mais ceci n'est pas nécessairement vrai pour une machine UNIX générique.
Un script avec des retours à la ligne DOS (\r\n) ne pourra pas s'exécuter car #!/bin/bash\r\n n'est pas reconnu, pas la même chose que l'attendu #!/bin/bash\n. La correction est de convertir le script en des retours chariots style UNIX.
#!/bin/bash echo "Ici" unix2dos $0 # Le script se modifie lui-même au format DOS. chmod 755 $0 # et modifie son droit d'exécution. # La commande 'unix2dos' supprime le doit d'exécution. ./$0 # Le script essaie de se lancer de nouveau. # Mais cela ne fonctionnera pas en tant que format DOS. echo "Là" exit 0 |
Un script shell commenaçant par #!/bin/sh peut ne pas se lancer dans un mode de compatibilité complète avec Bash. Quelques fonctions spécifiques à Bash pourraient être désactivées. Les scripts qui ont besoin d'un accès complet à toutes les extensions spécifiques à Bash devraient se lancer avec #!/bin/bash.
Un script peut ne pas faire un export de ses variables à son processus parent, le shell ou à l'environnement. Comme nous l'avons appris en biologie, un processus fils peut hériter de son parent, mais le contraire n'est pas vrai.
NIMPORTEQUOI=/home/bozo export NIMPORTEQUOI exit 0 |
bash$ echo $NIMPORTEQUOI bash$ |
Initialiser et manipuler des variables dans un sous-shell, puis essayer d'utiliser ces mêmes variables en dehors du sous-shell résultera en une mauvaise surprise.
Exemple 32-1. Problèmes des sous-shell
#!/bin/bash # Problèmes des variables dans un sous-shell. variable_externe=outer echo echo "variable_externe = $variable_externe" echo ( # Début du sous-shell echo "variable_externe à l'intérieur du sous-shell = $variable_externe" variable_interne=interne # Configure echo "variable_interne à l'intérieur du sous-shell = $variable_interne" variable_externe=interne # Sa valeur va-t'elle changer globalement? echo "variable_externe à l'intérieur du sous-shell = $variable_externe" # Fin du sous-shell ) echo echo "variable_interne à l'extérieur du sous-shell = $variable_interne" # Déinitialise. echo "variable_externe à l'extérieur du sous-shell = $variable_externe" # Non modifié. echo exit 0 |
Envoyer dans un tube la sortie de echo pour un read peut produire des résultats inattendus. Dans ce scénario, read agit comme si elle était lancée dans un sous-shell. A la place, utilisez la commande set (comme dans Exemple 11-14).
Exemple 32-2. Envoyer dans un tube la sortie de echo pour un read
#!/bin/bash # badread.sh: # Essai d'utiliser 'echo' et 'read' #+ pour affecter non interactivement des variables. a=aaa b=bbb c=ccc echo "un deux trois" | read a b c # Essaie d'affecter a, b et c. echo echo "a = $a" # a = aaa echo "b = $b" # b = bbb echo "c = $c" # c = ccc # L'affectation a échoué. # ------------------------------ # Essaie l'alternative suivante. var=`echo "un deux trois"` set -- $var a=$1; b=$2; c=$3 echo "-------" echo "a = $a" # a = un echo "b = $b" # b = deux echo "c = $c" # c = trois # Affectation réussie. # ------------------------------ # Notez aussi qu'un echo pour un 'read' fonctionne à l'intérieur d'un #+ sous-shell. # Néanmoins, la valeur de la variable change *seulement* à l'intérieur du #+ sous-shell. a=aaa # On recommence. b=bbb c=ccc echo; echo echo "un deux trois" | ( read a b c; echo "A l'intérieur du sous-shell: "; echo "a = $a"; echo "b = $b"; echo "c = $c" ) # a = un # b = deux # c = trois echo "-----------------" echo "A l'extérieur du sous-shell: " echo "a = $a" # a = aaa echo "b = $b" # b = bbb echo "c = $c" # c = ccc echo exit 0 |
Utiliser les commandes << suid >> à l'intérieur de scripts est risqué et peut compromettre la sécurité de votre système. [1]
Utiliser des scripts shell en programmation CGI peut être assez problématique. Les variables des scripts shell ne sont pas << sûres >>, et ceci peut causer un comportement indésirable en ce qui concerne CGI. De plus, il est difficile de << sécuriser >> des scripts shell.
Les scripts Bash écrits pour Linux ou BSD peuvent nécessiter des corrections pour fonctionner sur une machine UNIX commerciale. De tels scripts emploient souvent des commandes et des filtres GNU qui ont plus de fonctionnalités que leur contrepartie UNIX. Ceci est particulièrement vrai pour les utilitaires texte comme tr.
Danger is near thee -- Beware, beware, beware, beware. Many brave hearts are asleep in the deep. So beware -- Beware. | |
A.J. Lamb and H.W. Petrie |
[1] | Ajouter le droit suid sur le script lui-même n'a aucun effet. |
Précédent | Sommaire | Suivant |
Options | Niveau supérieur | Ecrire des scripts avec style |