Table des matières

L'âme d'un système UNIX : le shell (terminal)

Sujet : le shell (terminal, console, ligne de commande)
Niveau : Difficile
Auteur : smilebob (6 novembre 2004), révisé par calimarno le 15 septembre 2006

Introduction

Bien qu'aujourd'hui les logiciels possédant des interfaces graphiques soient les plus agréables à utiliser par les utilisateurs (en particulier, les novices en informatique), le shell (terminal) conserve une très grande utilité pour effectuer certaines tâches de manière rapide ou pour éventuellement résoudre des problèmes (typiquement, lorsque le serveur X ne veut pas démarrer). Vous trouverez ci-dessous quelques explications concernant les bases de la ligne de commande.

Définition

Le shell (ou terminal) est un programme d'interprétation d'une chaîne de caractères, qui, si elle est conforme au langage de commandes, est alors évaluée et exécutée.

C'est aussi un langage de programmation permettant d'écrire des fichiers de commandes (shell-scripts), utiles pour la gestion du système ou le lancement d'applications complexes.

Versions

Il existe différent shell, qui ont suivi différentes améliorations depuis le shell original d'Unix.

Syntaxe d'une commande Unix

La syntaxe standard d'une commande UNIX est la suivante :

$ commande -options arg1 arg2 arg3 

Les options varient en fonction de la commande, le nombre des arguments qui suivent dépend aussi de la commande.

Exemple n°1
$ sort -r mon-fichier 

sort (trier) permet de trier un fichier, l'option r (reverse), permet de trier en sens inverse le fichier. Généralement, pour introduire une option on la précède d'un tiret (-), mais il n'est pas nécessaire pour certaines commandes (comme tar, par exemple). L'argument unique de la commande est le nom du fichier : mon-fichier.

NB: Pour connaître la liste des options disponibles ainsi que leur signification, il suffit de consulter le manuel (commande man suivie du nom de la commande dont vous désirez connaître les options.)

Exemple n°2
$ cp -R mon-repertoire nouveau-repertoire 

La commande cp (copy) copie un répertoire (option R) vers un autre répertoire, on a ici deux arguments.

Exemple n°3
ps -ef

Avec cette commande les options e et f sont couplées.

Les entrées et les sorties

Il y a trois sortes d'entrées/sorties (ou flux de données), chacune identifiée par un numéro descripteur :

Redirection des entrées sorties

Quand vous lancez une commande dans un shell, le texte qui éventuellement s'affiche suite à l'exécution de la commande s'affiche par défaut directement dans le shell. On dit alors que le shell est la sortie standard.

Vous pouvez changer ce comportement, en tapant :

$ ma-commande > mon-fichier 

Tous les commentaires (les sorties) de la commande, ne vont pas apparaître dans le shell mais être écrits dans un fichier nommé mon-fichier. En d'autres termes, la sortie standard est redirigée vers ce fichier. Cela peut être utile, si vous avez une commande qui génère énormément de commentaires, et que vous voulez les récupérer, pour les exploiter par la suite, à la fin de l'exécution de la commande.

La redirection ”>” a pour effet de créer le fichier mon-fichier; si ce fichier existe déjà, il est tout simplement écrasé (supprimé et recréé), ce qui peut être gênant si vous ne voulez pas perdre ce qu'il contient.

Vous disposez donc de la redirection >> :

$ ma-commande >> mon-fichier 

Avec cette commande, le fichier mon-fichier n'est pas écrasé, mais la sortie standard (les commentaires de la commande) sont ajoutés en fin de fichier, à la suite du texte qui était déjà dans le fichier.

Les redirections marchent dans les deux sens, par exemple en tapant la commande suivante :

$ sort < mon-fichier 

Vous envoyez le contenu du fichier mon-fichier vers la commande sort (trier), celle-ci va donc trier le contenu du fichier. Par défaut le résultat sort sur la sortie standard, c'est à dire à l'écran, plus précisément sur le shell. Pour que le résultat soit sauvegardé dans un fichier et n'apparaisse plus à l'écran, il est possible d'utiliser la commande suivante :

$ sort < mon-fichier > fichier-trie 

L'expression > fichier_trie a pour effet d'envoyer le résultat de sort < mon-fichier dans le fichier fichier_trie.

Avec la redirection << la commande va lire les caractères jusqu'à la rencontre d'une certaine chaîne de caractères. Par exemple, avec la commande cat (catalogue, permet d'éditer le contenu d'un fichier).

$ cat << fin je tape du texte jusqu'à la chaîne de caractère fin 

En tapant la commande, vous revenez à la ligne, mais perdez le prompt, cat va lire (et éditer) les caractères que vous saisissez jusqu'à qu'il rencontre la chaîne fin, à ce moment là, le prompt apparaît à nouveau. Si vous voulez créer un fichier mon-fichier avec un peu de texte à l'intérieur, vous ferez :

$ cat << fin > mon-fichier je tape du texte qui sera sauvegardé dans mon-fichier.

Avec la commande :

$ > fichier-vide

Vous créez un fichier vide qui se nomme fichier-vide.

Redirection des erreurs

Par défaut les messages d'erreur s'affichent à l'écran (sortie standard par défaut), vous pouvez modifier ce comportement. On rappelle que la sortie d'erreur a comme numéro descripteur le “2”. Vous pouvez sauvegarder dans un fichier vos messages d'erreur, pour les analyser ultérieurement, en tapant :

$ cat mon-fichier 2>fichier-erreur 

Si on rencontre une erreur pendant l'exécution de la commande d'édition cat de mon-fichier (absence du fichier par exemple), le message d'erreur sera sauvegardé dans le fichier fichier-erreur.

En tapant :

$ sort mon-fichier > fichier-trie 

Vous redirigez le résultat de la commande sort mon-fichier vers le fichier nommé fichier-trie, la sortie standard (descripteur 1) n'est donc plus l'écran (plus précisément le shell ou terminal) mais le fichier fichier-trie.

Par défaut les messages d'erreur s'affichent dans le shell, vous pouvez faire en sorte qu'ils s'affichent dans le fichier fichier-trie, en tapant :

$ sort mon-fichier > fichier-trie 2>&1 

Avec la syntaxe >& vous indiquez que les messages d'erreurs seront redirigés vers la sortie standard qui est le fichier fichier-trie.

Les pipes

Un “pipe” (en français : “tube de communication”) permet de rediriger la sortie d'une commande vers une autre. En d'autres termes, pour rediriger les résultats (la sortie) d'une commande, on a vu qu'on pouvait taper :

$ commande1 > sortie1 

On redirige cette sortie vers une autre commande, ça devient donc une entrée pour cette dernière commande, pour cela vous tapez :

$ commande2 < sortie1

En fait la syntaxe (“|” est le symbole du pipe)

$ commande1|commande2

est totalement équivalente aux deux lignes de commandes précédentes.

Exemple

ls permet la visualisation de fichiers, en tapant ls, on obtient :

$ fichier1 fichier2 totofichier 

grep permet la recherche d'une chaîne de caractère dans une liste donnée. en tapant

$ grep toto *

(* signifie tous les fichiers, grep recherche la chaîne de caractère toto dans les noms de tous les fichiers)

Cette commande donne le résultat suivant :

totofichier

On a le même résultat avec le |, en tapant :

$ ls | grep toto

La première commande aura pour effet de lister le nom des fichiers se trouvant à l'endroit où l'on a tapé la commande, la sortie standard (le résultat de la commande) est donc une liste de nom, elle est redirigée vers la commande grep, qui va y chercher une chaîne de caractère contenant toto. Le résultat est donc aussi:

 totofichier 

Les caractères spéciaux

Vous trouverez ici une liste non exhaustive des différents caractères spéciaux du Shell.

Caractère Fonction
< Redirection de l'entrée
> Redirection de la sortie avec écrasement
>> Redirection de la sortie en mode ajout
2> Redirection de l'erreur avec écrasement
2>> Redirection de l'erreur en ajour
<<str Entrée en deux apparitions de str
<&n Redirection de l'entrée vers le fichier descripteur n
>&n Redirection de la sortie vers le fichier de descripteur n
>&- Fermeture de la sortie standard
<&- Fermeture de l'entrée standard
>&p Redirection de la sortie vers l'entrée du co-processus
<&p Redirection de la sortie du coprocessus vers l'entrée standard
; Enchaînement de commandes
| Mécanisme du “pipeline”
& Commande en arrière plan
( …) Groupement de commandes dans un shell fils
{ … } Groupement de commandes dans le shell courant
&& Enchaînement conditionnel de commandes avec ET logique
|| Enchaînement conditionnel de commandes avec OU logique
* Chaîne de caractère quelconque
? Un et un seul caractère quelconque
[ … ] Caractères défini dans l'ensemble
[ !… ] Caractères non-défini dans l'ensemble
`commande` Substitution de commande
$(commande) Substitution de commande

Valeurs de paramètres

Valeur Description
$n nième paramètre ( 0 < n < 10 )
${n} nième paramètre ( n > 9 )
$0 Nom de la commande en cours
$* Liste complète des paramètres
$@ Liste complète des paramètres
$#
$? Code de retour de la dernière commande ( 0 si pas d'erreur )
$$ PID du shell interpréteur
$! PID du dernier processus en arrière plan
$- Valeur courante des options du shell

Variables système

Variables Description
HOME Répertoire de connexion
IFS Séparateur interne de champs ( espace et tabulation par défaut )
MAIL Nom du fichier boîte aux lettres
PATH Chemin de recherche pour les commandes
PS1 Prompt principal
PS2 Prompt secondaire
SHELL Nom complet du shell
TERM Type de terminal
EDITOR Chemin d'accès à l'éditeur intégré
ENV Fichier d'environnement utilisateur
ERRNO Numéro d'erreur système
HISTFILE Chemin d'accès au fichier d'historique
HISTSIZE Nombre des dernières commande disponibles dans l'historique
PPID PID du processus père
PS3 Prompt de la commande select
PS4 Entête de la ligne de commande en mode trace
PWD Répertoire courant
RANDOM Nombre aléatoire
TMOUT Délai d'inactivité avant déconnexion

Les instructions de contrôle du shell

Comme dans tous langage évolué, le shell dispose d'instructions de contrôle (if, for ….)

for var [ in liste_valeurs ]
     do
         ...
     done
 case var in
    motif1)
      ...;;
    motif2)
      ...;;
    *)
      ...;; 
 esac
 if liste_cmde
 then
    ...
  [ elif liste_cmde
  then
    ...
  [else
    ... ] ]
 fi
 while liste_cde
   do
    ...
   done
 until liste_cde
   do
    ...
   done
<file>

  * La boucle ''select'' : 

<file>
 select var [ in liste_val ]
   do
    ...
   done