Mécanismes essentiels du shell
Présentation
Ce chapitre présente et explique de manière détaillée les fonctionnalités de base du shell couramment utilisées dans les commandes Unix.
Commandes internes et externes
Une commande Unix appartient à l’une des deux catégories suivantes.
1. Les commandes externes
Une commande externe est un fichier localisé dans l’arborescence. Par exemple, lorsqu’un utilisateur lance la commande ls, le shell demande au noyau Unix de charger en mémoire le fichier /usr/bin/ls.
Sont considérés comme commandes externes les fichiers possédant l’un des formats suivants :
-
Fichiers au format binaire exécutable.
-
Fichiers au format texte représentant un script de commandes (qui peut être écrit en shell ou dans un autre langage tel que Python, Perl...).
La commande file donne une indication sur le type de données contenues dans un fichier.
Exemples
La commande ls est un fichier au format binaire exécutable. Résultat de la commande file :
$ file /bin/ls
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
La commande monscript.sh est un script shell. Résultat de la commande file :
$ file /home/christie/monscript.sh
monscript.sh: ascii text
La commande monscript.pl est un script Perl. Résultat de la commande file :
$ file /home/christie/monscript.pl
monscript.pl: ascii text
L’argument de la commande file est un nom de fichier exprimé en relatif ou en absolu.
Les commandes externes sont exécutées par l’intermédiaire d’un shell enfant (cf. Figure 1).
Figure 1 : Exécution d’une commande externe
Les interpréteurs shell sont développés en Langage C. La fonction fork() du C permet à un processus de se dupliquer. La fonction exec() permet à un processus de se faire remplacer par un autre.
2. Les commandes internes
Une commande interne est un mot-clé du shell. C’est donc le shell qui exécute l’action....
Affichage à l’écran
1. La commande echo
bourne |
posix |
ksh |
bash |
La commande interne echo permet de réaliser des affichages à l’écran.
Exemple
$ echo Voici un livre sur la programmation shell!
Voici un livre sur la programmation shell!
$
Certains caractères ont, lorsqu’ils sont placés entre quotes (apostrophes ou guillemets), une signification spéciale. Ce sont des caractères d’échappement. La commande echo du bash devra être avec l’option-e pour que l’interprétation de ces caractères ait lieu.
Liste des caractères d’échappement
Caractère d’échappement |
Signification |
\\ |
Antislash |
\a |
Sonnerie |
\b |
Effacement du caractère précédent |
\c |
Suppression du saut de ligne en fin de ligne |
\f |
Saut de page |
\n |
Saut de ligne |
\r |
Retour chariot |
\t |
Tabulation horizontale |
\v |
Tabulation verticale |
\0xxx |
Valeur d’un caractère exprimée en octal |
a. Le caractère \n
Il sert à provoquer un saut de ligne.
Exemples avec un Bourne ou Korn shell
$ echo "Voici un saut de ligne\net encore un autre\net le saut de
ligne naturel de la commande echo"
Voici un saut de ligne
et encore un autre
et le saut de ligne naturel de la commande echo
$
Les quotes sont obligatoires :
$ echo a\nb
anb
$ echo "a\nb"
a
b
$
Exemples avec un bash
$ echo "a\nb"
a\nb
$ echo -e "a\nb"
a
b
$
b. Le caractère \c
Il sert à éliminer le saut de ligne naturel de la commande echo.
Le caractère \c doit se situer impérativement en dernière position de l’argument de echo (juste avant le guillemet fermant).
Exemples avec un Bourne ou Korn shell
$ echo "Premiere ligne" ; echo "Deuxieme ligne"
Premiere ligne ...
Le caractère ~ (tilde)
ksh |
bash |
Le caractère ~ représente le répertoire d’accueil de l’utilisateur courant.
Exemples
L’utilisateur courant se nomme christie :
$ id
uid=505(christie) gid=505(ociensa)
Le répertoire courant est /tmp :
$ pwd
/tmp
Copie du fichier /tmp/f1 dans le répertoire d’accueil (/home/christie) :
$ cp f1 ~
Copie du fichier /tmp/f1 sous le répertoire /home/christie/docs :
$ cp f1 ~/docs
Si le caractère ~ est immédiatement suivi d’un mot, ce dernier est considéré comme un nom d’utilisateur.
Exemples
Recopier le fichier f1 sous le répertoire d’accueil de l’utilisateur sebastien (nous supposons que les permissions adéquates sont positionnées) :
$ cp f1 ~sebastien
$ ls /home/sebastien/f1
f1
$
Recopier le fichier f1 sous le répertoire /home/sebastien/rep :
$ cp f1 ~sebastien/rep
$ ls /home/sebastien/rep
f1
La commande interne cd
Nous présentons ici les syntaxes particulières de la commande cd.
posix |
ksh |
bash |
Nous présentons ici les syntaxes particulières de la commande cd.
Exemples
La commande cd sans argument permet à l’utilisateur de revenir dans son répertoire d’accueil :
$ cd
Même chose en utilisant le caractère ~ :
$ cd ~
Se déplacer dans le répertoire d’accueil de l’utilisateur sebastien :
$ pwd
/home/christie
$ cd ~sebastien
$ pwd
/home/sebastien
Revenir dans le répertoire précédent avec cd - :
$ cd -
/home/christie
Substitution de noms de fichiers
De nombreuses commandes prennent des noms de fichier en argument. Ces derniers peuvent être cités littéralement ou être spécifiés de manière plus générique. Le shell propose un certain nombre de caractères spéciaux qui permettent de fabriquer des expressions utilisées comme modèles de noms de fichier.
1. Expressions basiques
bourne |
posix |
ksh |
bash |
a. Le caractère *
Il représente une suite de caractères quelconques (entre 0 et n caractères).
Exemples
$ ls
f12 f1.i FICa fic.c fic.s monscript.pl MONSCRIPT.pl ours.c
Afficher tous les noms de fichier se terminant par .c :
$ ls *.c
fic.c ours.c
Afficher tous les noms de fichier commençant par la lettre f :
$ ls f*
f12 f1.i fic.c fic.s
b. Le caractère ?
Il représente un caractère quelconque.
Exemples
Afficher tous les noms de fichier ayant une extension composée d’un seul caractère :
$ ls *.?
f1.i fic.c fic.s ours.c
Afficher tous les noms de fichier composés de quatre caractères :
$ ls ????
f1.i FICa
c. Les caractères [ ]
Une paire de crochets représente l’emplacement d’un seul caractère. Elle permet de spécifier la liste des caractères que l’on attend à une position bien précise dans le nom du fichier. Il est également possible d’utiliser les notions d’intervalle et de négation.
Exemples de syntaxe d’intervalles et de négation
Intervalles |
||
[a-z] |
une minuscule comprise entre a et z |
|
[a-zB-F] |
une minuscule comprise entre a et z OU une majuscule comprise entre B et F |
|
[A-Z0-9i] |
une majuscule OU un chiffre OU la lettre i |
Négation |
||
Le ! se positionne uniquement en première position à l’intérieur des crochets et exprime la négation... |
Séparateur de commandes
Le caractère spécial ; du shell permet d’écrire plusieurs commandes sur une même ligne. Les commandes sont exécutées séquentiellement.
Exemple
$ pwd
/home/christie
$ ls
$ mkdir rep ; cd rep ; pwd
/home/christie/rep
Redirections
Les redirections sont couramment utilisées dans les commandes Unix. Elles permettent de récupérer le résultat d’une ou de plusieurs commandes dans un fichier ou au contraire de faire lire un fichier à une commande. Cette partie expose de manière détaillée les différentes syntaxes possibles avec leur mécanisme interne associé.
Les redirections sont mises en place par le shell.
1. Entrée et sorties standards des processus
Les processus Unix ont, par défaut, leur fichier terminal ouvert trois fois, sous trois descripteurs de fichier différents. Un descripteur peut se voir comme un canal de communication.
a. Entrée standard
Le descripteur de fichier 0 est nommé également entrée standard du processus. Les processus qui attendent des informations de la part de l’utilisateur déclenchent une lecture sur le descripteur 0. Si ce dernier est associé au terminal, ce qui est le cas par défaut, cela se matérialise pour l’utilisateur par une demande de saisie au clavier.
La majorité des commandes utilisent l’entrée standard pour déclencher une saisie. Il existe cependant des exceptions. Par exemple, la commande passwd ouvre le fichier terminal sous un autre descripteur.
b. Sortie standard
Le descripteur de fichier 1 est nommé également sortie standard du processus. Par convention, un processus qui souhaite envoyer un message résultat à l’utilisateur doit le faire transiter via le descripteur 1. Si ce dernier est associé au terminal, ce qui est le cas par défaut, cela se matérialise pour l’utilisateur par un affichage à l’écran.
c. Sortie d’erreur standard
Le descripteur de fichier 2 est également nommé sortie d’erreur standard du processus. Par convention...
Tubes de communication
Un tube (pipe en anglais) permet de faire communiquer deux processus. Le tube est représenté par une barre verticale (combinaison de touches [Alt Gr] 6 sur un clavier AZERTY) située entre deux commandes Unix. Le résultat de la commande de gauche va partir dans le tube, tandis que la commande de droite va en extraire les données afin de les traiter.
Les figures 12 et 13 représentent le mécanisme interne associé au tube de communication.
Figure 9 : Mécanisme interne du tube de communication - Première étape
Figure 10 : Mécanisme interne du tube de communication - Deuxième étape
Quelles que soient les commandes présentes de chaque côté du tube, le shell de travail détecte le caractère | sur la ligne de commande et va engendrer un shell enfant (1) qui, à son tour, va faire de même (2). Le premier shell enfant (PID=205) dissocie sa sortie standard du terminal et la connecte sur l’entrée du tube (3). Le deuxième shell enfant (PID=206) dissocie son entrée standard du terminal et la connecte sur la sortie du tube (4).
Chaque shell enfant va se remplacer avec sa commande (5a et 5b). Chaque commande commence alors à s’exécuter. Lorsque la commande who écrit sur sa sortie standard, les messages partent dans le tube (6a). Parallèlement, la commande mail lit son entrée standard (6b), ce qui provoque l’extraction des données contenues dans le tube.
Quelques remarques importantes
-
La sortie d’erreur standard de la commande de gauche ne part pas dans le tube.
-
Pour que l’utilisation d’un tube ait un sens, il faut que la commande placée à gauche du tube envoie des données sur sa sortie standard et que la commande placée à droite lise son entrée standard....
Regroupement de commandes
Le regroupement de commandes peut être utilisé pour :
-
rediriger la sortie écran de plusieurs commandes vers un même fichier ou vers un tube ;
-
faire exécuter plusieurs commandes dans le même environnement.
Exemple
Seule la sortie standard de la deuxième commande est redirigée dans le fichier resultat.
$ date ; ls > resultat
ven. janv. 28 10:00:00 CET 2022
$ cat resultat
FIC
fichier
$
Les parenthèses ( ) et les accolades { } permettent de regrouper les commandes. Dans le premier cas, les commandes sont exécutées à partir d’un shell enfant, dans le deuxième cas à partir du shell courant.
1. Les parenthèses
Dans la plupart des cas, ce sont les parenthèses qui sont utilisées pour le regroupement de commandes.
Syntaxe
(cmde1 ; cmde2 ; cmde3)
Avec les parenthèses, un shell enfant est systématiquement créé et c’est ce dernier qui traite la ligne de commande (avec duplications ultérieures si nécessaire).
Premier exemple
Ici, l’utilisateur se sert des parenthèses pour rediriger la sortie standard de deux commandes :
$ (date ; ls) > resultat
$ cat resultat
lun. juin 13 17:23:50 CEST 2022
FIC
fichier
$
Deuxième exemple
Le changement de répertoire est fait dans un shell enfant. Les commandes pwd et ls ont donc pour répertoire courant /tmp :
$ pwd
/home/christie
$ (cd /tmp ; pwd ; ls) > listefic
$ cat listefic
/tmp (résultat de pwd)
dcopNYSrKn (liste des fichiers de /tmp)
listetmp
...
Lorsque l’exécution des trois commandes est terminée, le shell de premier niveau reprend la main. Son répertoire courant est toujours /home/christie.
$ pwd
/home/christie ...
Processus en arrière-plan
1. Principe
Les notions d’arrière-plan et d’avant-plan sont gérées par le shell.
Par défaut, les commandes sont lancées en avant-plan. Dans ce mode, le shell parent s’endort en attendant la fin de la commande. Il reprend la main uniquement lorsque la commande est terminée.
Le caractère & est un caractère spécial du shell qui permet de lancer la commande en arrière-plan. Le shell lance la commande et réaffiche immédiatement son prompt en attente d’une nouvelle commande. Comme le shell et la commande s’exécutent en parallèle et qu’ils sont tous deux liés au même terminal, il est conseillé de rediriger les sorties de la commande.
Exemple
Le shell affiche le PID de la commande (8247), ainsi que son index ([1]) dans la liste des tâches en arrière-plan lancées à partir de ce shell :
$ find / -size +2000 1>/tmp/resu 2 >/dev/null&
[1] 8247
$
Les processus qui s’exécutent en arrière-plan ne sont pas sensibles aux actions qui proviennent du clavier. Il est donc, par exemple, impossible de les tuer avec Ctrl C.
2. Contrôle de tâches (jobs)
jsh (Bourne shell avec Job Control) |
posix |
ksh |
bash |
Le shell dispose de commandes internes permettant à l’utilisateur d’agir sur les tâches du terminal courant qui sont en avant ou en arrière-plan. Le tableau suivant liste ces fonctionnalités.
Commande |
Action |
Touches [Ctrl] Z Uniquement pour processus en avant-plan |
Envoi du signal SIGTSTP : Passe le processus du terminal courant dans l’état Stoppé : le processus est toujours en mémoire, mais l’exécution est figée. Les commandes fg et bg permettent de reprendre l’exécution.... |
Exercices
1. Fonctionnalités diverses
a. Exercice 1 : commandes internes et externes
Les commandes umask et chmod sont-elles des commandes internes ?
b. Exercice 2 : génération de noms de fichiers
Soit la liste de fichiers suivante :
$ ls
bd.class.php header.inc.php install.txt readme.txt
essai index.php mail.class.php
1. |
Afficher les noms de fichiers se terminant par .php. |
2. |
Afficher les noms de fichiers ayant la lettre e en deuxième position. |
3. |
Afficher les noms de fichiers dont la première lettre est comprise entre a et e. |
4. |
Afficher les noms de fichiers qui ne commencent pas par une voyelle. |
Expressions étendues (ksh, bash)
5. |
Afficher les noms de fichiers qui ne se terminent pas par .php. |
6. |
Afficher les noms de fichiers qui ne se terminent ni par .txt ni par .php. |
c. Exercice 3 : séparateur de commandes
Comment écrire les deux commandes suivantes sur la même ligne ?
$ cd /tmp
$ ls -l
2. Redirections
a. Exercice 1
Lister tous les processus du système et rediriger le résultat dans un fichier.
b. Exercice 2
Soit la commande who -A, qui génère un message d’erreur :
$ who -A
who : option invalide -- 'A'
1. |
Relancer cette commande et rediriger les erreurs dans un fichier. |
2. |
Relancer cette commande et faire disparaître les erreurs, sans les rediriger dans un fichier disque. |
c. Exercice 3
Exécuter les commandes suivantes :
$ touch fic_existe
$ chmod 600 fic_existe fic_existepas
chmod: impossible d'accéder à "fic_existepas": Aucun fichier ou
dossier de ce type
1. |
Rediriger les résultats de la commande chmod dans un fichier, les erreurs dans un autre. |
2. |
Rediriger les résultats et les erreurs de la commande dans un même fichier. |
d. Exercice 4
Que fait...