Scripts shell faciles

Gazette Linux n°133 - Décembre 2006

par Blessen Cherian (Copyright © 2006) blessen@poornam.com

traduction par Azibi Mounia (tous droits réservés)


Introduction

Les scripts shell sont des suites de commandes, exécutées par séquences. L'écriture et l'exécution des scripts shell se fait en plusieurs étapes :

Étape 1: Ouvir le fichier dans un éditeur (par exemple "vi" ou "pico".).

      vi PremierScriptShell.sh
    

Étape 2: Tous les scripts shell doivent commencer par "#!/bin/bash" ou n'importe quel autre shell vous préférez. Cette ligne est appelée shebang, et même si elle ressemble à un commentaire elle n'en est pas un : elle indique au shell de l'interpéteur que le fichier est un script. Le chemin fourni doit être absolu (on ne peut, par exemple, pas utiliser "bash"). Le shebang doit être en première ligne du script, sans espace qui le précède.

Étape 3: Écrire le code que vous voulez développer. Notre premier script shell , que nous placerons dans le fichier "PremierScriptShell.sh", affichera l'habituel "Hello World"..

      #!/bin/sh
      echo "Hello World"
    

Étape 4: La prochaine étape est de rendre le script exécutable en utilisant la commande "chmod".

      chmod 744 PremierScriptShell.sh
    

ou

      chmod +x PremierScriptShell.sh
    

Étape 5: Exécuter le script. Elle peut être faite en entrant le nom du script dans la ligne de commande, précédée par son chemin. S'il est dans le répertoire courant, c'est très simple :

      bash$ ./PremierScriptShell.sh
      Hello World
    

Si vous voulez voir l'exécution étape par étape (ce qui peut être très utile en cas de bug), il faut lancer le script en ajoutant l'option "-x" :

      sh -x PremierScriptShell.sh
      + echo 'Hello World'
      Hello World
    

Pour voir le contenu d'un script, vous pouvez utilisez la commande "cat" ou encore l'ouvrir dans n'importe quel éditeur de texte:

      bash$ cat PremierScriptShell.sh
      #!/bin/sh
      echo Hello World
    

Les commentaires dans le shell

Dans les scripts shell, toutes les lignes commençant par # sont des commentaires.

      # Ceci est une ligne de commentaire.
      # Ceci en est une autre.
    

Il peut aussi y avoir des commentaires sur plusieurs lignes, pour cela il suffit d'utiliser ":" suivi d'une apostrophe :

      : 'Ceci est un ligne de commentaire.

      Encore une !

      Et celle ci aussi en est une ! '
    

Remarque : Cette méthode ne fonctionnera pas s'il y a une apostrophe dans les lignes de commentaires.

Variables

Comme vous devez le savoir, ou pas, les variables sont la partie la plus significative de n'importe quel langage, que ce soit Perl, C ou les scripts shell. Dans le shell, les variables sont classées en deux types : les variables système et les variables définies par l'utilisateur.

Variables système

Les variables système sont définies et enregistrées dans l'environnement du shell parent (le shell à partir duquel le script est exécuté). Ces variables sont aussi appelées variables d'environnement. Elles sont écrites en lettres capitales et peuvent être affichées en utilisant la commande "set". Voici quelques exemples de variables système : PWD, HOME, USER, etc. Leurs valeurs peuvent être affichées individuellement en utilisant la commande "echo". Par exemple, echo $HOME nous permettra de voir la valeur stockées dans la variable système HOMME.

Pour mettre à jour ou créer une variable système, il faut utiliser la commande "export" pour la rendre accessible aux shell fils (les shell lancés à partir du shell courant, y compris les scripts):

      bash$ SCRIPT_PATH=/home/blessen/scriptshell
      bash$ export SCRIPT_PATH
    

Les shells modernes permettent de faire ceci en en ligne de commande :

      bash$ export SCRIPT_PATH=/home/blessen/scriptshell
    

Variables utilisateurs

Ce sont les variables utilisées habituellement dans les scripts, celles qui ne sont pas rendues accessibles à d'autres programmes. Leurs noms ne peuvent pas commencer par un chiffre et sont écrites en lettres minuscules avec des tirets bas. Par exemple : "def_vartemp".

Pour assigner une valeur à une variable, il faut écrire le nom de la variable suivi de "=" et la valeur (par exemple : "def_valtemp=blessen"). Il ne doit y avoir aucun espace autour du signe égal. Pour utiliser ou afficher la variable, il faut utiliser la commande "echo" et précéder la variable du signe "$" :

      bash$ echo $def_valtemp 
      blessen
    

Le script qui suit définit la variable "username" et affiche sont contenu quand il est exécuté.

      #!/bin/sh

      username=blessen
      echo "Le nom d'utilisateur est $username"
    

Les arguments en ligne de commande

Ce sont des variables contenant les arguments d'un script quand il est exécuté. Ces variables sont accessibles avec $1, $2,...,$n, avec $1 le premier argument passé en ligne de commande, $2 le second, etc. Les arguments sont séparés par des espaces. $0 est le nom du script. La variable $# affiche le nombre d'arguments fournis, ce nombre est limité à 9 dans les anciens shell et est pratiquement illimité dans ceux modernes.

Considérons un script qui prends deux arguments et les affiche. Nous l'appelerons "lignecommande.sh".

      #!/bin/sh

      echo "La première variable est $1"
      echo "La seconde variable est $2"
    

Quand j'exécute "lignecommande.sh" avec des arguments comme "blessen" et 'lijoe", le résultat est :

      bash$ ./lignecommande.sh blessen lijoe
      La première variable est blessen
      La seconde variable est lijoe
    

Variable de statut de fin

Cette variable permet de savoir si la dernière commande exécutée a réussi ou non. Elle est représentée par $?. Une valeur de 0 signifie que la commande a été exécutée avec succès, tout autre nombre indique qu'il y a eu échec (certains programmes, comme mail, renvoient cependant d'autres chiffres que 0 pour indiquer le statut plutôt qu'un échec). C'est très utile pour les scripts.

Pour tester cela, créez un fichier "test" en exécutant touch test. Puis affichez le contenu du fichier.

      bash$ cat test
    

Vérifiez la valeur de $?.

      bash$ echo $?
      0
    

La valeur est 0 car la commande a été exécutée avec succès. Essayez maintenant de lancer "cat" sur un fichier qui n'existe pas :

      bash$ cat xyz1
      bash$ echo $?
      1
    

La valeur 1 montre que la commande ci-dessus a échoué.

La portée d'une variable

Je suis sûr que la plupart des programmeurs ont appris (et sûrement travaillé avec) les variables et le concepte de portée (c'est une définition du contexte dans lequel la variable est définie). Dans la programmation shell, on utilise aussi la portée d'une variable pour plusieurs tâches, même si c'est rarement nécessaire, cela peut être un outils utile. Dans le shell, il y a deux types de portée : globale et locale. Les variables locales sont définies en utilisant le mot clef "local" avant le nom de la variable lors de sa définition ; toutes les autres variables, sauf celles associées aux arguments des fonctions, sont globales et donc accessibles partout dans le script. Le script ci-dessous montre les différentes portées d'une variable locale et d'une autre globale :

      #!/bin/sh

      affiche()
      {
      local local_var=100
      global_var=blessen
      echo "La variable locale est $local_var"
      echo "La variable globale est $global_var"
      }

      echo "======================"
      affiche
      echo "======= dehors ========"
      echo "La variable locale en dehors de la fonction est $local_var"
      echo "La variable globale en dehors de la fonction est $global_var"
    

L'exécution du script donne :

      ======================
      La variable locale est 100
      La variable globale est blessen
      =======outside ========
      La variable locale en dehors de la fonction est 
      La variable globale en dehors de la fonction est blessen
    

Notez l'absence de valeur pour la variable locale en dehors de la fonction.

Entrée et sortie dans les scripts shell

Pour accepter les entrées avec le clavier, on utilise read. Cette commande va lire les valeurs entrées sur le clavier et les assigner à chaque variable spécifiées.

      read <variable_name>
    

Pour les sorties, on utilise la commande echo.

      echo "phrase à afficher"
    

Les opération arithmétiques dans les scripts shell

Comme les autres langages de scripts, le shell permet aussi d'utiliser les opérations arithmétiques telles que l'addition, la soustraction, la multiplication et la division. Pour les utiliser, il faut faire appel à la fonction expr. Par exemple "expr a + b" signifie "ajouter a et b".

Exemple :

      somme=`expr 12 + 20`
    

La syntaxe est similaire pour les opération de soustraction, division et multiplication. Il y a un autre moyen de faire des opérations arithmétiques ; entourer les variables et l'équation par des crochets précédés d'un signe $ :

      $[expression operation instruction]
    

Exemple :

      echo $[12 + 10]
    

[Notez que cette syntaxe n'est pas universelle, elle échouera par exemple dans le shell Korn. La syntaxe '$((...))' est plus adaptée, indifféremment du shell ; cependant il vaut mieux, sur le principe général de "laisser le shell faire ce qu'il fait de mieux et laisser le reste aux outils standards", utiliser un programme de calcul comme "bc" ou "dc" et la substitution de commande. Aussi, notez que l'arithmétique en shell se faire sur les entiers uniquement, alors que les deux méthodes ci-dessus n'ont pas ce problème. -- Ben]

Les instructions conditionnelles

Amusons-nous un peu avec une instruction conditionnelle comme "if condition". La plupart du temps, nous programmeurs shell, nous retrouvons dans des situations où nous devons comparer deux variables, et après exécuter certaines instructions dépendant de la véracité de la condition. Donc, dans de tels cas, on utilise l'instruction "if". La syntaxe est la suivante :

      if [ instruction conditionnelle ]
      then
      ... instructions ...
      fi
    

Le script ci-dessous va demander le nom d'utilisateur, et si celui ci est "blessen", va afficher un message montrant que la connexion a réussi. Sinon, il affichera "mauvais nom d'utilisateur".

      #!/bin/sh

      echo "Entrer votre nom d'utilisateur:"
      read username

      if [ "$username" = "blessen" ]
      then
      echo 'Bravo, vous êtes connecté.'
      else
      echo 'Désolée mauvais nom d'utilisateur.'
      fi
    

Rappelez vous de toujours écrire la variable à tester entre guillemets ; si vous ne le faites pas, le script échouera à cause de la mauvaise syntaxe quand la variable est vide. Aussi, les crochets (qui sont un alias pour la commande test) doivent être entourés d'espaces.

Comparaison de variables

Nous pouvons être amenés à comparer des variables. Si la valeur d'une variable à comparer est numérique, il faut utiliser ces options :

-eq Égal à
-ne Différent de
-lt Inférieur à
-le Inférieur ou égal à
-gt Supérieur à
-ge Supérieur ou égal à

Si ce sont des chaînes de caractères, il faut utiliser les options suivantes :

= Égal )
!= Différent de
< La premièe chaîne de caractère arrive avant la 2e dans l'ordre alphabétique
> La premièe chaîne de caractère arrive après la 2e dans l'ordre alphabétique

Les boucles

La boucle "for"

La boucle la plus utilisée est la boucle "for". Dans les scripts shell, il y en a deux types : une similaires à celle du langage C, et une boucle avec itérateur (utilisant des listes).

Syntaxe pour le premier typ de boucle "for" (utilisable seulement dans les shell modernes):

      for ((initialisation; condition; incrémentation/décrémentation))
      do
      ...instructions...
      done
    

Exemple:

      #!/bin/sh

      for (( i=1; $i <= 10; i++ ))
      do
      echo $i
      done
    

Cela va produire une liste de nombre de 1 à 10. La syntaxe pour la seconde boucle for, utilisable dans plus de shell :

      for <variable> in <liste>
      do
      ...instructions...
      done
    

Ce script va lire le contenu de "/etc/group" et afficher une ligne à la fois :

      #!/bin/sh

      compteur=0
      for i in `cat /etc/group`
      do
      compteur=`expr "$compteur" + 1`
      echo "La ligne $compteur est affichée"
      echo $i
      done

      echo "Fin du fichier"
    

Un autre exemple de la boucle "for" utilise "seq" pour générer une séquence :

      #!/bin/sh

      for i in `seq 1 5`
      do
      echo $i
      done
    

La boucle while

La boucle "while" est une autre boucle utile dans tous les langages de programmation; elle s'exécute jusqu'à ce que la condition spécifiée devienne fausse.

      while [ condition ]
      do
      ...instruction...
      done
    

Le scripte suivant assigne la valeur 1 à la variable num et ajoute 1 à la valeur num à chaque itération de la boucle, tant que la valeur de num est inférieure à 5.

      #!/bin/sh

      num=1

      while [$num -lt 5]; do num=$[$num + 1]; echo $num; done
    

Les instructions select et case

Similaire à la structure "switch/case" en C, la combinaison de "select" et "case" permet aux programmeurs shell d'utiliser les mêmes fonctionnalités. L'instruction "case" ne fait pas partie de "case", mais j'ai assemblé les deux pour illustrer leur utilisateur en programmation.

Syntaxe de select:

      select <variable> in <liste>
      do
      ...instructions...
      done
    

Syntaxe de case:

      case $<variable> in
      <option1>) instructions ;;
      <option2>) instructions ;;
      *) echo "Désolé, mauvaise option" ;;
      esac
    

L'exemple ci-dessous expliquera l'utilisation de select et case ensemble, et affichera les options impliquant la nécessité de redémarrer un composant de la machine. Quand l'utilisateur sélectionne une option, le script lance le service correspondant.

      #!/bin/bash

      echo "***********************"
      select opt in apache named sendmail
      do
      case $opt in
      apache) 	/etc/rc.d/init.d/httpd redémarrer;;
      named) 		/etc/rc.d/init.d/named redémarrer;;
      sendmail)	/etc/rc.d/init.d/sendmail redémarrer;;
      *) 			echo "Rien ne sera redémarré"
      esac
      echo "***********************"

      #Si le break ne figure pas ici, il n'y aura pas d'invite de commande
      break

      done
    

[Au lieu d'utiliser une instruction "break" explicite, qui n'est pas utile si vous voulez utiliser plus d'une des options présentées, il est beaucoup mieux d'inclure "Quit" comme dernière option dans la liste de select, avec une instruction y correspondant. -- Ben ]

Fonctions

Dans le monde moderne où les tous programmeurs utilisent le modèle OOP pour programmer, même nous, programmeurs shell ne sommes pas loin derrière. Nous pouvons aussi diviser le code en plusieurs parties appelée fonctions, et leur donner un nom dans le programme principal. Cette approche aide pour débugger et réutiliser le code, etc.

La syntaxe pour les fonctions est :

      <nom de la fonction> ()
      {	# début de la fonction
      instructions
      } 	# fin de la fonction
    

Les fonctions sont appelées en utilisant leurs noms dans le programme principal, suivi éventuellement par des arguments. Par exemple :

      #!/bin/sh

      sumcalc ()
      {
      sum=$[$1 + $2]
      }

      echo "Entrer le premier nombre:"
      read num1
      echo "Entrer le second nombre:"
      read num2

      sumcalc $num1 $num2

      echo "Résultat pour sumcalc: $sum"
    

Debugger les scripts shell

Parfois, on a besoin de débugger un programme. Pour ce faire, on utilise les options "-x" et "-v" du shell. L'option "-v" produit une longue sortie. L'option "-x" étendra chaque commande simple, la commande "for", la commande "case", la commande "select" , ou la commande arithmétique "for", afichant la valeur étendue de PS4, suivi par la commande et ses arguments étendus ou mots associés. Essayez les dans cet ordre, ils peuvent être très utiles quand vous n'arrivez pas à localiser le problème dans votre script.


Blessen Cherian

Je m'appelle Blessen et je préfère qu'on m'appelle Bless. Je me suis intéressé à Linux quand j'ai rejoins l'entreprise, Poornam Info Vision Pvt Ltd aussi connue sous le nom Bobcares. Ils m'ont donné accès à Linux.

Je suis diplômé d'informatique de l'Université d'Informatique, à Chengannur. J'ai fini mes études en 2001 et ai rejoint l'entreprise cette même année. Pendant mon travail, j'étais passionné de la sécurité sous Linux et j'ai très envie d'évoluer dans ce domaine.

Mes passes temps favoris sont de surfer sur internet, apprendre de nouvelles technologies et aider les autres. Durant mon temps libre, je programme aussi des logiciels libres et l'un d'entre eux est une version de formmail. Le projet s'appelle "Start Mail" qui est plus sécurisé que formmail.


Adaptation française de la Gazette Linux

L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux

Cet article est publié selon les termes de la Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.

Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site http://www.traduc.org/Gazette_Linux

Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.