Sous Unix, on appelle shell l’interpréteur de commandes qui fait office d'interface entre l'utilisateur et le système d’exploitation. Les shells sont des interpréteurs : cela signifie que chaque commande saisie par l’utilisateur (ou lue à partir d’un fichier) est syntaxiquement vérifiée puis exécutée.
Il existe de nombreux shells qui se classent en deux grandes familles :
zsh est un shell qui contient les caractéristiques des deux familles précédentes. Néanmoins, le choix d’utiliser un shell plutôt qu’un autre est essentiellement une affaire de préférence personnelle ou de circonstance. En connaître un, permet d’accéder aisément aux autres. Lorsque l’on utilise le système GNU/Linux (un des nombreux systèmes de la galaxie Unix), le shell par défaut est bash (Bourne Again SHell). Ce dernier a été conçu en 1988 par Brian Fox dans le cadre du projet GNU1. Aujourd’hui, les développements de bash sont menés par Chet Ramey.
Un shell possède un double aspect :
En premier lieu, un shell doit fournir un environnement de travail agréable et puissant. Par exemple, bash permet (entre autres) :
Illustrons cet ajustement de configuration par un exemple. Le shell permet d’exécuter une commande en mode interactif ou bien par l'intermédiaire de fichiers de commandes (scripts). En mode interactif, bash affiche à l’écran une chaîne d’appel (appelée également prompt ou invite), qui se termine par défaut par le caractère # suivi d’un caractère espace pour l’administrateur système (utilisateur root) et par le caractère $ suivi d’un caractère espace pour les autres utilisateurs. Cette chaîne d’appel peut être relativement longue.
Celle-ci est constituée du nom de connexion de l’utilisateur (sanchis), du nom de la machine sur laquelle l’utilisateur travaille (jade) et du chemin absolu du répertoire courant de l’utilisateur (/bin). Elle indique que le shell attend que l’utilisateur saisisse une commande et la valide en appuyant sur la touche entrée. Bash exécute alors la commande puis réaffiche la chaîne d’appel. Si l’on souhaite raccourcir cette chaîne d’appel, il suffit de modifier la valeur de la variable prédéfinie du shell PS1 (Prompt Shell 1).
$ pwd
/bin => pwd affiche le chemin absolu du répertoire courant
$
La nouvelle chaîne d’appel est constituée par le caractère $ suivi d’un caractère espace.
Les shells ne sont pas seulement des interpréteurs de commandes mais également de véritables langages de programmation. Un shell comme bash intègre :
Ex : $ a=5 => affectation de la valeur 5 à la variable a
$
$ echo $((a +3 )) => affiche la valeur de l’expression a+3
8
$
L’opérateur |, appelé tube, est un opérateur caractéristique des shells et connecte la sortie d’une commande à l’entrée de la commande suivante.
Ex : $ lpstat -a
HP-LaserJet-2420 acceptant des requêtes depuis jeu. 14 mars 2013 10:38:37 CET HP-LaserJet-P3005 acceptant des requêtes depuis jeu. 14 mars 2013 10:39:54 CET
$
$ lpstat -a | wc -l
2
$
La commande unix lpstat permet de connaître les noms et autres informations relatives aux imprimantes accessibles. La commande unix wc munie de l’option l affiche le nombre de lignes qu’elle a été en mesure de lire.
En connectant avec un tube la sortie de lpstat -a à l’entrée de la commande wc –l, on obtient le nombre d’imprimantes accessibles sur le réseau.
Même si au fil du temps de nouveaux types de données comme les entiers ou les tableaux ont été introduits dans certains shells, ces derniers manipulent essentiellement des chaînes de caractères : ce sont des langages de programmation orientés chaînes de caractères. C’est ce qui rend les shells à la fois si puissants et si délicats à utiliser.
L’objet de ce document est de présenter de manière progressive les caractéristiques de bash
comme langage de programmation.
L’étude d’un shell tel que bash en tant que langage de programmation possède plusieurs avantages :
La manière la plus simple de connaître le shell que l’on utilise est d’exécuter la commande unix
ps qui liste les processus de l’utilisateur :
Ex : $ ps
PID TTY TIME CMD
6908 pts/4 00:00:00 bash => l’interpréteur utilisé est bash
6918 pts/4 00:00:00 ps
$
Comme il existe plusieurs versions de bash présentant des caractéristiques différentes, il est important de connaître la version utilisée. Pour cela, on utilise l'option –-version de bash.
Ex : $ bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc.
...
$
La version de bash qui sera utilisée est la version 4.2.
La syntaxe générale d'une commande (unix ou de bash) est la suivante :
[ chemin/]nom_cmd [ option ... ] [ argument ... ]
C'est une suite de mots séparés par un ou plusieurs blancs. On appelle blanc un caractère tab
(tabulation horizontale) ou un caractère espace.
Un mot est une suite de caractères non blancs. Cependant, plusieurs caractères ont une signification spéciale pour le shell et provoquent la fin d'un mot : ils sont appelés méta-caractères (ex : |, <).
Bash utilise également des opérateurs (ex : (, ||) et des mots réservés :
! case do done elif else esac
fi for function if in select then
time until while { } [[ ]]
Bash distingue les caractères majuscules des caractères minuscules. Le nom de la commande est le plus souvent le premier mot.
Une option est généralement introduite par le caractère tiret (ex : -a) ou dans la syntaxe GNU par deux caractères tiret consécutifs (ex : --version). Elle précise un fonctionnement particulier de la commande.
La syntaxe [ elt ... ] signifie que l’élément elt est facultatif (introduit par la syntaxe [ elt ]) ou bien présent une ou plusieurs fois (syntaxe elt …). Cette syntaxe ne fait pas partie du shell ; elle est uniquement descriptive (méta-syntaxe).
Les arguments désignent les objets sur lesquels doit s’exécuter la commande.
Ex : ls -l RepC RepD : commande unix ls avec l’option l et les arguments RepC et RepD
Lorsque l’on souhaite connaître la syntaxe ou les fonctionnalités d’une commande cmd (ex : ls ou bash) il suffit d’exécuter la commande man cmd (ex : man bash). L’aide en ligne de la commande cmd devient alors disponible.
Commandes internes
Une commande interne est une commande dont le code est implanté au sein de l’interpréteur de commande. Cela signifie que, lorsqu’on change de shell courant ou de connexion, par exemple en passant de bash au C-shell, on ne dispose plus des mêmes commandes internes.
Exemples de commandes internes : cd , echo , for , pwd
Sauf dans quelques cas particuliers, l’interpréteur ne crée pas de processus pour exécuter une commande interne.
Les commandes internes de bash peuvent se décomposer en deux groupes :
¤ Commandes simples
Parmi l’ensemble des commandes internes, echo est l’une des plus utilisée :
echo :
Cette commande interne affiche ses arguments sur la sortie standard en les séparant par un espace
et va à la ligne.
Ex : $ echo bonjour tout le monde
bonjour tout le monde
$
Dans cet exemple, echo est invoquée avec quatre arguments : bonjour, tout, le et monde.
On remarquera que les espacements entre les arguments ne sont pas conservés lors de l’affichage : un seul caractère espace sépare les mots affichés. En effet, le shell prétraite la commande, éliminant les blancs superflus.
Pour conserver les espacements, il suffit d’entourer la chaîne de caractères par une paire de
guillemets :
Ex : $ echo “bonjour tout le monde”
bonjour tout le monde
$
On dit que les blancs ont été protégés de l'interprétation du shell.
Pour afficher les arguments sans retour à la ligne, on utilise l’option -n de echo.
Ex : $ echo -n bonjour
bonjour$
La chaîne d’appel $ est écrite sur la même ligne que l’argument bonjour.
¤ Commandes composées
case ... esac if ... fi for ... done select ... done
until ... done while ... done [[ ... ]] ( ... )
{ ... } (( … ))
Seuls le premier et le dernier mot de la commande composée sont indiqués. Les commandes composées sont principalement des structures de contrôle.
Une commande externe est une commande dont le code se trouve dans un fichier ordinaire. Le shell crée un processus pour exécuter une commande externe. Parmi l’ensemble des commandes externes que l’on peut trouver dans un système, nous utiliserons principalement les commandes unix (ex : ls, mkdir, cat, sleep) et les fichiers shell.
La localisation du code d'une commande externe doit être connue du shell pour qu'il puisse exécuter cette commande. A cette fin, bash utilise la valeur de sa variable prédéfinie PATH. Celle-ci contient une liste de chemins séparés par le caractère : (ex : /bin:/usr/bin). Par exemple, lorsque l’utilisateur lance la commande unix cal, le shell est en mesure de l’exécuter et d’afficher le calendrier du mois courant car le code de cal est situé dans le répertoire /usr/bin présent dans PATH.