Logo Khaganat
Traductions de cette page?:

Cette page n'est pas tagué correctement.

Ceci est une ancienne révision du document !


Bonnes pratiques

Cette page liste dans une première partie quelques bonnes pratiques. Dans une seconde partie il sera question d'une sorte de trucs & astuces, des options méconnues de certaines commandes plus ou moins connues. Enfin en troisième partie, on revient un petit peu aux bonnes pratiques, aux choses auxquelles faire attention lorsque l'on administre un système.

Libre à vous d'étoffer l'article, toute contribution est bienvenue !

Bash / Shellscript

Shebang!

La première ligne d'un script shell contient toujours ce qu'on appelle le shebang, qui est utile pour indiquer au système qu'il s'agit d'un script shell (ou php, ou python, ou perl, etc). Dans le cas de bash, le shebang se présente sous cette forme :

#!/bin/bash

Parfois on voit aussi des scripts shell commencer par #!/bin/sh. La bonne pratique veut que l'on n'utilise cette forme (avec /bin/sh et non /bin/bash) que pour les scripts d'init, car le shell /bin/sh n'est pas nécessairement bash. Dans le cas de Debian notamment, il s'agit de dash, un shell allégé spécifiquement pour lancer ces scripts d'initialisation. Si vous comptez utiliser des spécificités bash, donc, préférez #!/bin/bash.

Sous-commandes (subcommands)

Il existe en shellscript deux possibilités pour exécuter des sous-commandes :

`avec des backticks`

ou alors

$(avec $parenthèses)

La première solution ne devrait être utilisée que dans les cas où cela s'avère absolument nécessaire (un script écrit pour de très vieux shells Bourne non-POSIX). Dans tous les cas il faut préférer la forme $().

Référence : http://mywiki.wooledge.org/BashFAQ/082

Largeur

Pour des raisons historiques, la convention veut que les lignes d'un script ne dépassent pas les 88 caractères. Si toutefois vous deviez écrire des lignes plus longues que ça, vous pouvez les étaler sur plusieurs lignes en mettant \ (barre oblique inversée + espace) avant chaque retour à la ligne.

Indentation

Attention, troll incoming ! Il n'y a pas de convention à ce jour. Généralement, on voit trois variantes (si vous en connaissez d'autres, n'hésitez pas) :

  • 2 espaces
  • 4 espaces
  • 1 tabulation

Noms des variables

Encore un troll… On peut écrire le nom des variables en $MAJUSCULE ou en $minuscule (ou en $mIXeD, mais c'est plus moche qu'autre chose, ça rend le tout illisible – autant écrire du brainfuck). Une convention veut que les noms des variables soient écrits en minuscules, avec un préfixe pour éviter la collision avec des noms réservés (comme par exemple $PATH, cf. la documentation de bash pour une liste complète). Cela pourrait ressembler à ça : $my_email, $my_source_path, etc.

Fonctions

Déclarer une fonction sans utiliser le mot-clef function, c'est obsolète.

Toujours utiliser des guillemets

Parfois un exemple vaut mille mots :

my_sentence="Cachez ces bits             que je ne saurais voir !"
echo $my_sentence
Cachez ces bits que je ne saurais voir !
echo "$my_sentence"
Cachez ces bits             que je ne saurais voir !

eval

Ne jamais utiliser eval, à moins de savoir ce que l'on fait ! eval fait que du code est exécuté deux fois. Si par exemple une variable contient du code, eh bien il sera exécuté. Cela est potentiellement une faille de sécurité béante, si on ne fait pas attention à ce qu'on fait.

Plus de détails ici https://mywiki.wooledge.org/BashFAQ/048

Fail early

C'est une expression à prendre au pied de la lettre : si une erreur doit avoir lieu, cela doit se passer le plus tôt possible. Par conséquent, une bonne pratique est, avant même d'écrire le code que l'on veut que notre script exécute, de vérifier si toutes les commandes qui y seront utilisées sont bien existantes :

my_needed_commands="sed awk lsof who"
missing_counter=0
for needed_command in $my_needed_commands; do
  if ! hash "$needed_command" >/dev/null 2>&1; then
    printf "Command not found in PATH: %s\n" "$needed_command" >&2
    ((missing_counter++))
  fi
done

if ((missing_counter > 0)); then
  printf "At least %d commands are missing in PATH, aborting\n" "$missing_counter" >&2
  exit 1
fi

On pourrait même pousser l'idée plus loin en testant les options des commandes utilisées (je pense par exemple à awk, pour qui il existe plein d'implémentation différentes).

Code de sortie

Toujours sortir du script avec un bon code de sortie (“exit status”) et éviter à tout prix de toujours terminer avec un code 0. Si ce n'est pas fait comme il faut, le script peut potentiellement produire des erreurs et continuer tout de même. Cela devient encore pire si le script est utilisé dans une suite de plusieurs commandes.

Liens

http://mywiki.wooledge.org/BashGuide/Practices (la bible bash, à avoir absolument sur votre table de chevet !) http://wiki.bash-hackers.org/scripting/style

Commandes unix

find

grep / wc

On voit très très souvent des oneliners qui, pour compter le nombre de lignes font ceci :

[commande] | wc -l

Jusque là aucun souci. En revanche, quand on veut filtrer, très souvent on utilise grep :

[commande] | grep "machin" | wc -l

Là, ça commence à piquer les yeux. OK, vous allez dire que je suis un vieux de la vieille qui voit le mal partout, qui cherche à économiser le moindre octet en mémoire, qu'on n'est plus à une époque où la mémoire était chère et rare… Qu'à cela ne tienne ! Plus c'est court, plus c'est élégant, mieux c'est !

Ça commence à piquer les yeux parce-que grep sait très bien compter tout seul !

[commande] | grep -c "machin"

Et voilà ! L'option -c de grep retourne le nombre de lignes où machin a été trouvé.

Sysadmin en général

Reboot

Quoi que l'on fasse comme modification sur un système, il faut toujours veiller à ce qu'après un redémarrage la machine se retrouve dans un état identique à celui dans lequel elle était avant ce redémarrage.

Par exemple, quand on ajoute une route sur la CLI, bien veiller à ce que la route soit aussi configurée “en dur”. Dans le cas de Debian, on peut mettre la commande dans par exemple /etc/network/interfaces en ajoutant up devant la commande qu'on a exécuté.

CLI :
route add -host ftp.fr.debian.org gw 192.168.100.253
/etc/network/interfaces :
iface eth0 inet static
    address [...]
up route add -host ftp.fr.debian.org gw 192.168.100.253
down route del -host ftp.fr.debian.org gw 192.168.100.253

Attention à la seconde ligne avec down, ce n'est pas route add mais route del, pour supprimer la route lors de l'extinction ou du redémarrage.

Cela n'est qu'un exemple. À chaque modification il faut se poser la question : “Est-ce que ma modification est «reboot-proof» ?”

CC Attribution-Share Alike 4.0 International Driven by DokuWiki
fr/bestpractices.1522217234.txt.gz · Dernière modification : 2021/12/03 19:18 (modification externe)

Licences Mentions légales Accueil du site Contact