Les interpréteurs de commandes, ou shells
Description
L’interpréteur de commandes (aussi appelé shell) est un programme qui constitue une interface indispensable pour permettre une interaction efficace entre l’homme et le système d’exploitation. Il lit les commandes tapées au clavier, et les traduit en création de processus : il permet ainsi l’utilisation facile de l’ordinateur par les administrateurs et les utilisateurs.
Sans ce type de programme, un système d’exploitation est difficilement utilisable. Sa puissance et sa simplicité ont un rôle très important dans l’adhésion qu’un système d’exploitation peut emporter auprès du public d’utilisateurs. Le succès et la forte diffusion d’UNIX à partir de 1979 sont en partie dus à la puissance et à la simplicité de son interpréteur de commandes de l’époque, le Bourne shell.
Historique
Le premier shell a été créé par Ken Thompson (l’un des principaux concepteurs d’UNIX) et est apparu en 1971 dans UNIX v1. Il disposait déjà à l’époque de la redirection des entrées/sorties des commandes, depuis ou vers des fichiers, réalisable grâce à une syntaxe simple. Il ne comportait presque pas de commandes intrinsèques (built-in), mais de très nombreuses fonctionnalités des shells actuels étaient déjà présentes, en particulier la gestion des métacaractères des expressions régulières.
La redirection de la sortie d’un programme vers un autre programme, connue aujourd’hui sous le nom de pipe ou tube de communication interprocessus, est apparue dans la version 3 d’UNIX (UNIX v3) suite à une suggestion de Doug Mc Illroy. La syntaxe était plus compliquée et plus ambiguë que la syntaxe actuelle. Elle a évolué au fil des versions pour devenir celle que nous utilisons de nos jours.
Les variables shell sont apparues vers 1975, dans un shell d’UNIX PWB (Programmer’s Work Bench) que l’on doit entre autres à John Mashey.
Le Bourne shell (de Steve R. Bourne) fut créé en 1976, avec son lot d’évolutions, fruits notamment de discussions entre Steve Bourne, Dennis Ritchie et John...
Les caractères de sélection de noms de fichiers
1. La découverte des expressions régulières par l’utilisateur
Lorsque l’on commence à travailler sur un système de type UNIX (UNIX, AIX, HP-UX, Solaris, Linux...), les premières expressions régulières que l’on découvre sont généralement celles de l’interpréteur de commandes, ou shell.
Dès qu’il faut manipuler des groupes de fichiers, pour les effacer, les déplacer ou effectuer n’importe quel autre type de traitement, on ressent rapidement le besoin de pouvoir désigner de façon simple et concise les groupes de fichiers à traiter.
On les désigne alors par ce qu’ils ont en commun, et qui est souvent en rapport avec une partie de leur nom faisant référence à une caractéristique commune, par exemple :
-
des fichiers HTML, possédant l’extension .html,
-
des fichiers objets, possédant l’extension .o,
-
les fichiers sources d’un module logiciel XX, par exemple préfixés par xx_.
Ces désignations sont effectuées à l’aide d’expressions de sélection (ou patterns) utilisant des métacaractères qui permettent, grâce à la signification particulière qui leur est donnée par l’outil les interprétant (le shell dans le cas présent), d’effectuer un filtrage sur les noms des fichiers d’un répertoire.
Les métacaractères du shell sont peu nombreux et très simples à utiliser.
2. La spécificité des expressions de sélection du shell
Les expressions génériques utilisables avec le shell ne sont pas ce que l’on a couramment l’habitude de désigner par les termes expressions régulières. Il s’agit plutôt d’expressions de sélection (ou de filtrage) de noms de fichiers. Ces expressions ne contiennent pas le caractère / (barre oblique, ou slash) et ne servent qu’à sélectionner les noms courts (basename en anglais) des fichiers ou répertoires. On peut en accoler plusieurs, séparées par des / pour sélectionner des noms longs (pathname) ou absolus (full pathname).
Sur UNIX et ses dérivés, le caractère...
Les autres caractères spéciaux
Parmi les caractères ASCII, d’autres que ceux vus précédemment ont une signification particulière pour le shell, sans toutefois être utilisés pour évaluer des noms de fichiers. En voici quelques-uns :
’ |
simple quote : suppression de la signification des caractères spéciaux |
" |
double quote : suppression de la signification des caractères spéciaux, à l’exception de quelques-uns |
` |
quote inversée (back quote) : lancement de commande |
( ) |
parenthèses : lancement d’un sous-shell |
{ } |
accolades : significations diverses, notamment utilisées pour l’évaluation des variables |
; |
point-virgule : séparateur de commandes |
& |
esperluette ou « et commercial » : lancement de commande en arrière-plan et séparateur de commandes |
| |
« pipe » : tube de communication inter-processus |
< > |
inférieur et supérieur : redirection d’entrée ou de sortie |
|
espace : séparateur d’arguments |
\ |
antislash : changement de signification d’un caractère |
~ |
tilde : référence à un utilisateur |
# |
dièse : commentaire |
= |
égal : opérateur d’affectation |
! |
point d’exclamation : référence à une commande précédente... |
La commande de traitements sélectifs
Il existe un autre contexte où l’on peut utiliser les métacaractères pouvant servir à la génération de noms de fichiers, c’est le cas où l’on veut effectuer un traitement en fonction d’une valeur (contenu d’une variable ou résultat de commande). Dans ce contexte, l’expression régulière ne sert pas à sélectionner des noms de fichiers ou de répertoires, mais à déterminer si une chaîne suit un modèle particulier, afin d’effectuer un traitement associé. La fonction du shell dont il est question ici peut être considérée comme un aiguillage permettant d’effectuer telle ou telle action en fonction de la chaîne à traiter. Il s’agit de la fonction case (un équivalent du switch en langage C).
Syntaxe
En syntaxe compatible Bourne shell :
case chaîne in
expr_1) traitement_1
;;
expr_2) traitement_2
;;
...
expr_N) traitement_N
;;
*) traitement_par_defaut
;;
esac
ou en syntaxe compatible C-shell :
switch ( chaîne )
case expr1 :
traitement_1
breaksw
case expr2 :
traitement_2
breaksw
...
case expr_N :
traitement_N
breaksw
default :
traitement_par_défaut
breaksw
endsw
1. Le métacaractère * ...
Mise en garde sur le décodage des arguments
Lorsqu’une ligne de caractères est passée au shell, suite à un appui sur la touche [Entrée] (ENTER ou RETURN sur un clavier anglophone), le shell effectue une analyse élaborée de la chaîne de caractères qu’il a lue, à la recherche de noms de processus à lancer, de variables à évaluer, d’expressions de sélection à interpréter...
Il est important de savoir que si aucun nom de fichier ne correspond à une expression de sélection spécifiée, le shell n’effectuera (sauf directive contraire), aucune substitution, et passera l’expression de sélection sans modification à la commande lancée, comme dans l’exemple suivant :
$ echo /bin/*ABCDEF*
/bin/*ABCDEF*
$ args /bin/*ABCDEF*
ARGC = 2
ARGV[ 1 : length = 13] = "/bin/*ABCDEF*"
Ainsi, le fait d’utiliser, sans les encadrer dans des simples quotes ou doubles quotes, des chaînes de caractères comportant des métacaractères du shell (même si elles ont peu de risques de correspondre à des noms de fichiers) est une très mauvaise habitude qui a généralement pour effet, un jour ou l’autre, d’aboutir à un bug ou à une faille de sécurité, souvent difficiles à trouver, lorsqu’un nom de fichier correspond à l’expression de sélection spécifiée.
Prenons comme exemple la commande clush, du cluster shell, qui permet de lancer des commandes sur un groupe de serveurs ou un ensemble de noeuds d’un cluster de calcul : elle utilise une syntaxe utilisant les caractères...
Exercices
1. Exercice 1
Solutions
args A\\B
args 'AB'
args "AB"
Ces trois commandes afficheront le résultat suivant :
ARGC = 2
ARGV[ 1 : length = 4] = "AB"
2. Exercice 2
Comment passer la chaîne "alpha" (incluant les doubles quotes) à la commande echo ?
Solutions
echo '"alpha"'
"alpha"
ou :
echo \"alpha\"
"alpha"
La chaîne "alpha" est encadrée entre des simples quotes : les doubles quotes sont conservées.
3. Exercice 3
Comment passer la chaîne ’beta’ (incluant les simples quotes) à la commande echo ?
Solutions
echo "'beta'"
'beta'
ou :
echo \'beta\'
'beta'
La chaîne ’beta’ est encadrée entre des doubles quotes : les simples quotes sont conservées.
4. Exercice 4
Passer les caractères suivants à un programme, comme la commande echo par exemple :
1. ’ : une simple quote
2. " : une double quote
3. . : le caractère point
4. ; : le point-virgule
5. & : le ET commercial
6. | : le "pipe"
7. / : le slash
8. \ : l’antislash
9. $x : le dollar suivi du caractère x
10. # : le dièse
11. !!: deux points d’exclamation
12. * : le caractère étoile
13. [abc] : une chaîne entre crochets
14. < : le caractère inférieur
Solutions
1.
echo "'"
(simple quote encadrée entre deux doubles quotes)
ou :
echo \'
(simple quote précédée d’un antislash afin de lui enlever...