Sites


Introduction à la ligne de commande

CommandLineIntro: CheckingExit

État de sortie

Lorsque vous saisissez des commandes, vous pouvez d'ordinaire indiquer si elles ont ou non fonctionné. Les commandes qui ne sont pas en mesure d'effectuer ce que vous avez demandé affichent habituellement un message d'erreur. C'est suffisant si vous saisissez chaque commande à la main et observez la sortie, mais parfois (par exemple, si vous écrivez un script), vous voulez que vos commandes réagissent différemment lorsqu'une commande échoue.

Pour faciliter cette tâche, quand une commande se termine, elle retourne un état de sortie. L'état de sortie n'est normalement pas affiché ; en remplacement, elle est placée dans une variable (un emplacement mémoire nommé) nommé « $? ». L'état de sortie est un nombre situé entre 0 et 255 (inclusivement) ; zéro signifie succès, et toute autre valeur correspond à un échec.

Un moyen de voir l'état de sortie d'une commande consiste à utiliser la commande echo pour l'afficher :

$ echo "ceci fonctionne bien"
ceci fonctionne bien
$ echo $?
0
$ hhhhhh
bash: hhhhhh: command not found
$ echo $?
127

Maintenant, nous allons décrire diverses façons de gérer les erreurs.

if / then

Gérer une erreur est un exemple d'une action que vous effectuez de manière conditionnelle : si un évènement se produit, alors vous voulez agir. Le terminal fournit une commande composée – une commande qui exécute d'autres commandes – appelée if. La forme la plus simple est :

if
  <commande>
then
  <commmands-if-successful>
fi

Nous allons partir d'un exemple de base, puis l'améliorer pour le rendre plus utile. Après qu'on a saisi if et appuyé sur la touche Entrée, le terminal sait que nous sommes au milieu d'une commande composée, ainsi il affiche une invite différente (>) pour nous le rappeler.

$ if
> man ls
> then
> echo "Vous en savez maintenant plus sur ls"
> fi
La page de manuel de ls défile
Vous en savez maintenant plus sur ls

L'exécution de cette commande fait s'afficher la page de manuel de ls. En quittant avec la touche q, la commande man se termine avec succès et la commande echo s'exécute.

Gérer l'échec d'une commande

Ajouter une clause else permet de spécifier quoi exécuter en cas d'échec :

if
  <command>
then
  <commands-if-successful>
else
  <commands-if-failed>
fi

Lançons apropos si la commande échoue.

$ if
> man draw
> then
> echo "Vous en savez maintenant plus sur draw"
> else
> apropos draw
> fi
...
liste de résultats pour apropos draw
...

Cette fois, la commande man a échoué parce qu'il n'existe pas de commande draw, activant la clause else.

&& et ||

La structure (construct) if-then est très utile, mais plutôt verbeuse pour faire s'enchaîner des commandes dépendantes.  Les opérateurs « && » (and) et « || » (or) fournissent un format plus compact.

command1 && command2 [&& command3]...

L'opérateur && relie deux commandes. La seconde commande ne s'exécutera que si la première présente un état de sortie de zéro, c'est-à-dire, si la première commande a été un succès. On peut utiliser des instances multiples de l'opérateur && sur la même ligne.

$ mkdir mylogs && cd mylogs && touch mail.log && chmod 0660 mail.log

Voici un exemple de commandes multiples, dont chacune suppose que la précédente s'est exécutée avec succès. Si nous devions utiliser la structure if-then pour ce faire, nous nous serions retrouvées avec une masse encombrante de « if » et « then ».

Notez que l'opérateur && le court-circuite, c'est-à-dire que, si une commande échoue, aucune commande postérieure n'est exécutée. Nous tirons profit de cette propriété pour empêcher des effets indésirables (comme la création de mail.log dans le répertoire incorrect dans l'exemple ci-dessus).

Si && est l'équivalent de then, l'opérateur || est l'équivalent de else.  Il fournit un mécanisme pour spécifier quel commande exécuter si la première échoue.

command1 || command2 || command3 || ...

Chaque commande dans la chaîne ne sera lancée que si la précédente commande n'a pas été un succès (c'est-à-dire, un état de sortie autre que zéro).

$ cd Desktop || mkdir Desktop || echo "Desktop directory not found and could not be created"

Dans cet exemple, nous allons tenter d'entrer dans le répertoire Desktop, faute de quoi nous le créons et informons l'utilisateur via un message d'erreur.

Grâce à cette connaissance, nous pouvons écrire une fonction helpme efficace et compacte. Nos exemples précédent ont montré les deux opérateurs employés isolément, mais ils peuvent être également mélangés.

$ function helpme() {
  man $1 && echo "you now know more about $1" || apropos $1
}

Comme vous le soupçonnez probablement, l'« echo » « you now know more about…» n'est pas exactement la commande la plus utile. (elle pourrait même ne pas être précise, peut-être la page de man a-t-elle affiché trop d'options et semé la confusion chez l'utilisateur). Nous reconnaissons de tout cœur que nous l'avons introduite simplement pour faire correspondre la syntaxe if-then originale.  Maintenant que nous connaissons l'opérateur ||, il est possible de simplifier la fonction en :

$ function helpme() {
  man $1 || apropos $1
}

Que signifie un état de sortie ?

Jusqu'ici, nous n'avons pris en considération que la différence entre les états de sortie zéro et non-zéro. Nous savons que zéro signifie succès et non-zéro indique un échec. Mais quel type d'échec ? Certaines valeurs de sortie peuvent être employées pour des paramètres de sortie spécifiés par l'utilisateur, de sorte que leur signification risque de varier d'une commande à l'autre. Cependant, il existe certaines significations largement acceptées pour certaines valeurs.

Par exemple, si vous exécutez une commande inexistante (ex.en saisissant incorrectement une commande existante ou en omettant son emplacement correct), vous devez vous attendre à recevoir la notification standard de « command not found » généralement associée avec l'état de sortie 127.  We encountered this value at the very beginning of this chapter:

$ hhhhhh
bash: hhhhhh: command not found
$ echo $?
127

Un autre état de sortie à signaler est « permission denied », habituellement associé au code 126.  Lorsque vous rencontrez cette valeur, il peut valoir la peine d'améliorer le niveau d'attention. La commande que vous essayez d'exécuter exige des droits d'accès dont vous ne disposez pas. Il existe certains cas fréquents. 

Tout d'abord, vous avez tenté d'exécuter en tant qu'utilisateur normal un commande qui requiert des privilèges de superutilisateur (root). Dans ce cas, si vous savez ce que vous faites, vous devez vous connecter en tant que superutilisateur et ensuite exécuter la commande à nouveau. Cependant, si vous plein de doutes à propose de cette commande, il serait probablement judicieux de passer du temps à vous documenter à ce sujet. Si cette commande requiert des privilèges de superutilisateur,  elle risque d'être potentiellement dangereuse si elle n'est pas utilisée correctement.

En second lieu, vous pouvez essayer de lancer un logiciel installé avec les privilèges erronés. Par exemple, il se peut que collaboriez avec d'autres personnes dans le développement d'une application  hébergée dans l'emplacement personnel d'un autre utilisateur et que cet utilisateur ait oublié de vous autoriser à lancer l'exécutable. Les commandes chown et chmod peuvent aider.

Il existe même la possibilité que vous tentiez d'obtenir des informations sur votre système sans modifier l'état du système, donc vous pouvez penser que cette opération devrait être possible sans avoir besoin d'être superutilisateur, ce qui est souvent possible, mais pas toujours. Par exemple, vous pouvez vérifier l'état des services « ssh » et « at » : le premier est normalement lisible tandis que l'autre ne peut pas :

$ /etc/init.d/sshd status
sshd (pid 1234) is running...

$ /etc/init.d/atd status
bash: /etc/init.d/atd: Permission denied
$ echo $?
126

Il peut arriver qu'une commande exécutée prenne beaucoup de temps pour se terminer. Si cette commande est nécessaire pour générer ou modifier des informations requises par vos commandes ultérieures, alors vous devrez vérifier que la commande chronophage que vous avez lancée n'a pas mis fin à son exécution de façon imprévue. Ce n'est pas la même chose que de vérifier que la commande s'est terminée correctement (état de sortie 0). Cette commande peut rencontrer une condition d'erreur et décider de se terminer par un code de sortie différent de zéro. Il est cependant très différent le cas où il est impossible à la commande de choisir son état de sortie parce qu'elle ne peut pas se terminer du tout. Si une boucle infinie à l'intérieur de la commande nécessite une intervention externe ou une intervention externe prématurée substitue la commande s'exécutant correctement, un signal INT (qui est une interruption utilisateur) peut-être être envoyé à la commande en appuyant sur Ctrl + c ou mettre fin à la commande via :

$ kill -int pid-of-the-command

Un tel type de terminaison risque de modifier la sortie attendue de la commande interrompue et compromettre une quelconque manipulation ultérieure de cette sortie. Lorsqu'un signal INT termine une commande, un état de sortie 130 est retourné. Par exemple, observez la commande yes qui nécessite un Ctrl + c pour se terminer :

$ yes
y
y
y
...
# press ctrl+c 
$ echo $?
130

Ce chapitre couvre le concept d'état de sortie et son utilisation pour contrôler le flux de vos commandes et scripts. Nous espérons que vous le quitterez avec un état de zéro !

Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.

Vous devriez rafraîchir la page.