diff --git a/unix/shell/commande.tml b/unix/shell/commande.tml new file mode 100644 index 0000000..5e7565b --- /dev/null +++ b/unix/shell/commande.tml @@ -0,0 +1,500 @@ + + + + +Commandes + + + +

Le shell en ligne de commande

+ +

Créer des processus

+ +

Le shell a la faculté de lancer de nombreux programmes, sinon +tous. C'est une des raisons pour lesquelles on peut dire que c'est un +outil extrêmement puissant. +

+ +

Qu'est-ce qu'un processus ?

+ +

Lancer un programme, c'est créer un +processus. Tautologisons : un processus est une +instance d'exécution d'un programme, c'est-à-dire +l'exécution particulière d'un programme universel (i.e qui +n'est pas réductible à l'une de ses exécutions).

+ +

Par exemple, si je lance Mozilla, un processus se crée, du nom de +mozilla. Ensuite, sans fermer ce programme, je lance une +deuxième fois Mozilla ; un nouveau processus se crée, du nom +de mozilla également. J'ai donc deux processus +distincts, même s'ils concernent le même programme. Et à chaque +fois que je lance un programme, un processus se crée. +

+ +

Généalogie des processus

+ +

Dans notre exemple, nous avons deux processus +mozilla. Ils sont indépendants l'un de l'autre : +quoi qu'il puisse se passer dans l'un, cela ne devrait pas influer sur +le comportement de l'autre. +

+ +

Toutefois, s'ils sont indépendants l'un de l'autre, tous deux +dépendent du processus qui les a lancés. Eh oui, le shell +est un programme comme un autre, donc chacune de ses exécutions +correspond également à la création d'un processus. Si +vous lancez trois shells en même temps, par exemple dans trois +terminaux différents, vous aurez trois processus shell +distincts.

+ +

+Les processus entretiennent entre eux des relations de parenté. Mais +comme les processus ont tous le même sexe, chaque processus +n'a qu'un parent. Un processus peut avoir plusieurs enfants. +

+ +

Le shell est, comme nous venons de le voir, un processus qui +peut enfanter d'autres processus. Par exemple, à chaque fois +que je tape mozilla, mon shell crée un processus +mozilla.

+ + +

Lancer des processus en arrière-plan

+

+Par défaut, le shell met le processus enfant en +avant-plan. Cela veut dire que si je tape simplement : +

+ +
+chaland ~ mozilla
+
+ +

+le processus mozilla prend la main, et le shell ne +réagit plus (il n'affiche même plus l'invite de commande) avant +la fin du processus enfant. Ce n'est que lorsque le processus +mozilla prend fin (si je ferme ce programme, par exemple) +que le shell reprend la main. +

+ +

Ce comportement par défaut n'est parfois pas très pratique. Par +exemple, si je veux lancer Mozilla, mais aussi Emacs et d'autres +programmes qui s'ouvrent dans leur propre fenêtre, je suis obligé +d'ouvrir à chaque fois un nouveau terminal avec un nouveau shell, et +ce uniquement pour y taper une commande, après quoi le shell se +retrouve inutilisable jusqu'à la fin de chacun de ces +programmes.

+ +

Il faudrait donc que l'on puisse lancer des processus enfants en +arrière-plan, de telle sorte que ces processus se lancent +dans leur propre fenêtre et me permettent toutefois de dialoguer avec +le shell sans avoir à :

+ + +

Pour cela, il faut ajouter le signe « & » à la +fin d'une ligne de commande. On peut ainsi taper :

+ +
+chaland ~ mozilla &
+chaland ~ mozilla &
+chaland ~
+
+ +

et de la sorte, un même shell peut engendrer +autant de processus que vous voulez.

+ + +

Émanciper un processus enfant

+

La vie est déjà plus pratique comme cela. Mais parfois, on +aimerait que le processus enfant survive au processus parent. Car par +défaut, la mort d'un processus parent entraîne celle de +tous ses enfants. Par exemple, si le shell qui a enfanté les +deux processus mozilla vient à décéder (si je le +ferme brutalement, ou s'il plante), les deux processus +mozilla le suivront dans la mort.

+ +

+Il faudrait donc qu'un processus parent puisse émanciper des +processus enfants, pour que sa propre mort n'entraîne pas les +leurs. Pour cela, il faut utiliser les symboles +« &! ». Par exemple, si je tape : +

+ +
+chaland ~ mozilla &!
+chaland ~ mozilla &!
+chaland ~
+
+ +

puis que je ferme brutalement le shell en tapant +Ctrl-D et en ignorant d'éventuels avertissements, le shell +disparaîtra, mais pas les processus mozilla.

+ + +

Arguments et options

+

Jusqu'ici, l'exemple de processus enfant que nous avons pris +était relativement simple : il s'agissait de la commande +mozilla, que l'on peut lancer en tapant simplement son +nom.

+ +

+Jusqu'ici, on peut se dire que la ligne de commande, c'est comme quand +on clique sur une icône, sauf que c'est plus fatigant. Effectivement, +pourquoi se fatiguer à taper une suite de caractères quand il +suffit d'appuyer une ou deux fois sur le bouton d'une souris ? +

+ +

+C'est dans l'usage des arguments et des options que la ligne de commande +commence à révéler une partie de sa puissance, et de sa nette +supériorité sur les interfaces graphiques. +

+ + +

Les arguments

+

Un argument est une suite de caractères que l'on donne à une +commande et qui lui indique comment se comporter. Les options sont un +type d'argument.

+ + +

Exemples

+ +

Par exemple, si je veux ouvrir le fichier hermocrate.txt +avec l'éditeur de texte nano, j'ai le choix entre deux +possibilités :

+ + + +

Ou encore, pour reprendre l'exemple de Mozilla, si je veux aller voir +la page des tuteurs et que ce n'est pas ma page d'accueil par défaut +(ce qui est un tort !), je peux taper :

+ +
chaland ~ mozilla http://www.tuteurs.ens.fr/
+ +

Les options

+

+Les options sont un cas particulier d'arguments, qui donnent au +programme que l'on exécute toutes sortes d'information, souvent +plus ou moins périphériques, en général moins importantes +que les arguments. +

+ +

Sous Unix, les options commencent généralement par un +tiret. Certaines options peuvent à leur tour prendre des +arguments.

+ +

Par exemple, si l'on veut ouvrir un fichier au format MS-DOS, on peut +taper :

+ +
chaland ~ nano -D hermocrate.txt
+ + +

Options à arguments

+ +

+L'option -r de nano prend un argument ; +ainsi, si l'on veut que Nano coupe les lignes au bout de 75 +caractères, on doit ouvrir Nano en tapant : +

+ +
chaland ~ nano -r 75 hermocrate.txt
+ + +

Options à nom long

+ +

Traditionnellement, et pur des raisons de concision, la majorité +des options, sous Unix, est composée d'un tiret et d'une seule +lettre. Toutefois, pour des raisons pratiques, il peut également +exister des noms d'option longs ; ils sont en général +précédés, non d'un, mais de deux tirets. Exemple :

+ +
chaland ~ nano --fill=75 hermocrate.txt
+ +

Dans cet exemple, il se trouve que l'option à nom +long --fill= équivaut à l'option à nom +court -r. Mais toutes les commandes courtes n'ont pas +systématiquement leur équivalent à nom long, et vice versa.

+ +

Jokers et citations

+ +

Raccourcis pour les noms de fichiers : les +jokers

+ +

+Il est souvent ennuyeux d'avoir à taper une longue liste de fichiers +pour les donner en arguments à une commande, comme : +

+ +
cc -o foo bar.c gee.c buz.c gog.c
+ +

+Pour éviter ces problèmes, on peut utiliser des jokers +(wildcards en anglais). Pourquoi ce nom ? Eh bien, dans +certains jeux de cartes, le joker permet de remplacer n'importe quelle +carte ; dans le shell, les jokers permettent de remplacer n'importe +quel caractère ou n'importe quelle séquence de caractères. +

+ +

+Il existe principalement trois types de jokers : +

+ + + +

L'étoile : *

+ +

+Une étoile * dans un nom de fichier est +interprétée par le shell comme « n'importe quelle séquence de +caractères » (mais ça ignore les fichiers dont le nom commence par un +point). Exemple : +

+ +
cc -o foo *.c
+ +

+Pour interpréter l'étoile, le shell va faire la liste de tous les noms de +fichiers du répertoire courant qui ne commencent pas par . et +qui finissent par .c. Ensuite, il remplace *.c +par cette liste (triée par ordre alphabétique) dans la ligne de commande, et +exécute le résultat, c'est-à-dire par exemple : +

+ +
cc -o foo bar.c buz.c foo.c gee.c gog.c
+ +

Le point d'interrogation : ?

+ +

+On a aussi le point d'interrogation ?, qui +remplace un (et exactement un) caractère quelconque (sauf un point en début +de nom). Par exemple, ls *.? liste tous les dont l'extension +ne comporte qu'un caractère (.c, .h...). +

+ +

Les crochets : []

+ +

+La forme [abcd] remplace un caractère quelconque parmi +a, b, c, d. Enfin, +[^abcd] remplace un +caractère quelconque qui ne se trouve pas parmi a, b, +c, d. +

+ +

Exemple

+ +
echo /users/*
+ +

+affiche à peu près la même chose que +

+ +
ls /users
+ +

+(La commande echo se contente d'afficher ses arguments.) +

+ +
+

+&icone.attention; Attention : +

+ + +
+ +
+

+Interlude : comment effacer un fichier nommé +?* ? On ne peut pas taper rm ?* car le shell +remplace ?* par la liste de tous les fichiers du répertoire +courant. On peut taper rm -i * qui supprime tous les +fichiers, mais en demandant confirmation à chaque fichier. On répond +n à toutes les questions sauf rm: remove  ?*. +Autre méthode: utiliser les mécanismes de citation. +

+
+ +

Contourner les jokers : la citation (quotation)

+ +

+Avec tous ces caractères spéciaux, comment faire pour passer des +arguments bizarres à une commande ? Par exemple, comment faire +afficher un point d'interrogation suivi d'une étoile et d'un dollar par +echo ?

+ +

+On ne peut pas les taper directement dans la ligne de commande (ici, +avec le shell zsh), car le shell essaye de les interpréter +comme des jokers : +

+ +
chaland ~ echo ?*$
+zsh: no matches found: ?*$
+ +

Il faut donc indiquer au shell de ne pas interpréter ces caractères +comme des jokers. Pour cela, nous allons utiliser des mécanismes fournis +par le shell : les quotations (mot anglais +signifiant citation). +

+ +

+Les mécanismes de citation sont les suivants : +

+ + + + + +

Le backslash (\)

+ +

+ Il suffit de précéder un caractère spécial d'un backslash, et le shell +remplace ces deux caractères par le caractère spécial seul. Évidemment, le +backslash est lui-même un caractère spécial. +

+ +

+Exemples : +

+ +
+chaland ~ $ echo \?\*\$
+?*$
+chaland ~ $ echo \\\?\\\*\\\$
+\?\*\$
+ +

Les apostrophes ou simples quotes (')

+ +

+Un autre moyen est d'inclure une chaîne de caractères entre apostrophes +(simples quotes) '. Tout ce qui se trouve entre deux +apostrophes sera passé tel quel par le shell à la +commande. Exemple : +

+ +
+chaland ~ $ echo '$?*'
+$?*
+ +

Les guillemets doubles ou doubles quotes (")

+ +

+Les guillemets se comportent comme les apostrophes, à une exception près: les +dollars et les backslashes sont interprétés entre les guillemets. +Exemple : +

+ +
+chaland ~ $ echo "$HOME/*"
+/users/87/maths/doligez/*
+ +

+Une technique utile: Quand on juxtapose deux chaînes de caractères +quotées, le shell les concatène, et elles ne forment qu'un argument. +Exemple : +

+ +
+chaland ~ $ echo "'"'"'
+'"
+ +

+Quant aux interactions plus compliquées (backslashes à l'intérieur des +guillemets, guillemets à l'intérieur des apostrophes, etc.), le meilleur moyen +de savoir si ça donne bien le résultat attendu est d'essayer. La commande +echo est bien utile dans ce cas. +

+ +

Les backquotes (`)

+ +

+Dernière forme de citation : `commande`. Le +shell exécute la commande indiquée entre backquotes, lit la +sortie de la commande mot par mot, et remplace ` +commande ` par la liste de ces mots. +Exemple : +

+ +
+chaland ~ $ echo `ls`
+Mail News bin foo lib misc mur notes.aux notes.dvi notes.log
+notes.tex planar text
+chaland ~ $ ls -l `which emacs`
+-rwxr-xr-t  1 root   taff   978944 Jul 16  1991 /usr/local/bin/emacs
+ +

+La commande which cmd employée ci-dessus affiche sur sa +sortie le nom absolu du fichier exécuté par le shell quand on lance la +commande it cmd : +

+ +
+chaland ~ $ which emacs
+/usr/local/bin/emacs
+ + + +

Vous êtes maintenant en mesure de faire ces exercices pour vous +entraîner.

+ + +
+Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez. +Modifications : Nicolas George, Baptiste Mélès. +Dernière modification le . +
+ + + diff --git a/unix/shell/entreesortie.tml b/unix/shell/entreesortie.tml new file mode 100644 index 0000000..db5cfc9 --- /dev/null +++ b/unix/shell/entreesortie.tml @@ -0,0 +1,392 @@ + + + + +Entrée/sortie + + + +

Entrée, sortie, redirection

+ +

Entrée et sortie

+ +

Que sont l'entrée et la sortie d'une commande ?

+ +

+Un programme consiste à traiter des données, et à renvoyer des données +transformées : il transforme des informations, et c'est pourquoi +l'on parle d'informatique.

+ +

Prenons le programme hachoir, par exemple : on y +fait entrer des choses, elles sortent sous une autre forme, et dans +l'intervalle, elles subissent des transformations régulières. Par +exemple, on fait entrer une vache, il en ressort du steak haché ; +on y fait entrer des carottes, il en ressort des carottes rapées. +

+ +

+Deux concepts permettent de modéliser cette transformation +d'informations : les concepts d'entrée et de +sortie. L'entrée, c'est la vache ou les carottes ; +la sortie, c'est le steak haché ou les carottes +rapées. +

+ +

Sortie standard et sortie d'erreur

+ +

+Mais cette première distinction entre entrée et sortie ne suffit pas, +car la sortie d'un programme, c'est-à-dire les messages qu'il renvoie, +sont de deux ordres : il y a les messages normaux relevant +de la transformation d'informations (par exemple le steak haché ou les +carottes rapées), mais il y a aussi des messages d'erreur.

+ +

Par exemple, si vous mettez, sur le tapis roulant qui mène au +hachoir, un objet trop gros pour y rentrer, le hachoir, s'il est bien +conçu, devra vous prévenir qu'il n'arrive pas à hacher un objet si +gros. Et ce message, quoiqu'il sorte aussi bien du hachoir que le steak +haché, ne doit pas être traité de la même façon à sa sortie, et n'est +pas suivi des mêmes conséquences. C'est pourquoi l'on distingue la +sortie standard et la sortie d'erreur. +

+ + + + +

Comportement par défaut

+ +

+Pour résumer, chaque commande a donc :

+ + +

Par défaut, l'entrée standard est le clavier, la sortie standard est +l'écran, et la sortie d'erreur est aussi l'écran.

+ +

C'est sur le clavier que vous tapez ; ce que vous tapez et ce +que renvoient les programmes s'inscrit à l'écran ; les messages +d'erreur renvoyés par les programmes s'affichent à l'écran. +

+ +

Les redirections

+ +

+Mais il ne s'agit là que du comportement par défaut, et pas d'un +comportement obligatoire. Vous pouvez tout à fait orienter différemment +vos programmes.

+ +

Par exemple, si vous donnez une vache comme entrée au hachoir, vous +pouvez orienter la sortie vers une imprimante (au lieu de l'écran, +proposé par défaut), et vous imprimerez ainsi du steak haché.

+ +

+Ou encore, vous pouvez donner un plant de carottes comme entrée au +programme cueillette, et envoyer la sortie (c'est-à-dire +les carottes cueillies) au programme hachoir. +

+ +

+Nous allons étudier successivement : +

+ + + +

+Ces différentes configurations esquissent la grammaire d'une utilisation +très performante des fonctionnalités du shell ; vous saurez +en effet comment brancher un fichier sur l'entrée ou sur la sortie d'une +commande, et comment brancher la sortie d'une commande sur l'entrée +d'une autre. Il n'y a pas d'autre combinaison possible. +

+ + +

Rediriger la sortie dans un fichier : >

+ +

+On peut rediriger la sortie standard d'une commande vers un +fichier (caractère « > »). Le résultat de la +commande sera placé dans le fichier au lieu de s'afficher sur l'écran. +Exemple : +

+ +
chaland ~ $ ls -l > foo
+ +

+Le résultat de ls -l ne s'affiche pas à l'écran, mais il est placé +dans le fichier foo. On peut alors taper +

+ +
chaland ~ $ less foo
+ +

+(ou more foo) +pour lire le fichier page par page. +

+ + +

Ajouter la sortie à un fichier : >>

+ +

On veut parfois ajouter la sortie d'un programme à un fichier, sans +effacer ce qui précède. Or, par défaut, si l'on tape plusieurs fois +

+ +
chaland ~ $ ls -l > foo
+ +

+à chaque fois, le contenu antérieur du fichier foo est +écrasé par le contenu ultérieur. +

+ +

+Pour éviter cela, il existe l'outil de redirection >>. Ainsi, si +vous tapez plusieurs fois +

+ +
chaland ~ $ ls -l >> foo
+ +

+le fichier foo contiendra à la suite tout ce que +vous a renvoyé la commande. +

+ + + + +

Rediriger l'entrée : <

+ +

+On peut aussi rediriger l'entrée standard d'une commande (caractère +« < »). La commande lira alors le fichier au +lieu du clavier. Exemple : +

+ +
chaland ~ $ elm leroy < foo
+ +

+envoie par mail à Xavier Leroy le résultat de la commande ls -l de +tout à l'heure. +

+ +

+On peut aussi taper more < foo qui est équivalent à +more foo car more sans argument lit son entrée +standard et l'affiche page par page sur le terminal. +

+ +

Connecter la sortie d'une commande sur l'entrée d'une autre : +|

+ +

+Il devient rapidement ennuyeux de taper : +

+ +
chaland ~ $ ls -l > foo
+chaland ~ $ less < foo
+chaland ~ $ rm foo
+ +

+On peut se passer du fichier intermédiaire (foo dans notre +exemple) grâce à un pipe (caractère +« | »). Un pipe connecte directement la sortie +standard d'une commande sur l'entrée standard d'une autre commande. +Exemple : pour afficher page par page la liste des fichiers du +répertoire courant, faire +

+ +
chaland ~ $ ls -l | less
+ +

+Le pipe, ou tube, est d'un usage très courant, et rend beaucoup de +services. +

+ + + +

Succès et erreur

+ +

+On a parfois besoin de savoir si une commande a réussi ou non avant d'en +lancer une autre. Les indicateurs && et +|| permettent, respectivement, de lancer une commande si +(et seulement si) la précédente a réussi ou échoué. +

+ +

+Par exemple, si j'ai un fichier foo, j'obtiens : +

+ +
+chaland ~ $ ls foo && echo "J'ai un fichier foo."
+foo
+J'ai un fichier foo.
+
+ +

+Si je n'ai pas de fichier foo, le message ne s'affiche +pas. En revanche, si je tape alors : +

+ +
+chaland ~ $ ls foo || echo "Je n'ai pas de fichier foo."
+ls: foo: No such file or directory
+Je n'ai pas de fichier foo.
+
+ + + +

Redirection des sorties standard et d'erreur

+ +

+Il est parfois utile de rediriger la sortie standard et la sortie +d'erreur vers un même endroit. Pour cela, on utilise le motif +2>&1 avant la redirection. +

+ + + + + + + + + + + + + + + + + + + + + + +
Fonction Bourne shell (sh, bash) Z-shell (zsh)
Redirige la sortie d'erreur (2) et la sortie standard (1) sur l'entrée +de la commande suivante2>&1 | |&
Redirige la sortie d'erreur et la sortie standard dans un fichier2>&1 > >&
Redirige la sortie d'erreur et la sortie +standard à la fin d'un fichier existant2>&1 >>>>&
+ +

Remarques

+ +

+Normalement, une redirection avec > sur un fichier qui +existe déjà efface le contenu du fichier avant d'y placer le résultat de la +commande. Les shells ont des options pour demander confirmation, ou +refuser d'effacer le fichier. +

+ +

+Une ligne de commandes contenant des | s'appelle un pipe-line. +Quelques commandes souvent utilisées dans les pipe-lines sont: +

+ + + +

Exemples

+ +
cat glop buz > toto
+ +

+Concatène les fichiers glop et buz et place le +résultat dans toto. +

+ +
wc -w /usr/dict/words
+ +

+Affiche le nombre de mots du dictionnaire Unix. +

+ +
grep gag /usr/dict/words | tail
+ +

+Affiche les 10 derniers mots du dictionnaire qui contiennent la chaîne +gag. +

+ +

Récapitulatif

+ +

+La panoplie complète des redirections est la suivante : +

+ + + + + +

Vous êtes maintenant en mesure de faire ces exercices pour vous +entraîner.

+ + +
+Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez. +Modifications : Nicolas George, Baptiste Mélès. +Dernière modification le . +
+ + + diff --git a/unix/shell/index.tml b/unix/shell/index.tml new file mode 100644 index 0000000..2bc6905 --- /dev/null +++ b/unix/shell/index.tml @@ -0,0 +1,220 @@ + + + + +Shell + + + +

Présentation du shell

+ +

+Le mot shell signifie « coquille » en anglais. Il +s'agit du programme que vous utilisez régulièrement sur les machines +Unix de l'ENS (que ce soient les Sun, les PC sous FreeBSD ou autres +dérivés d'Unix), et qui interprète les commandes. Par exemple, vous y +tapez pine ou mutt, forum, +cc, mozilla, etc. +

+ +

+Mais quel rapport avec une coquille ? Eh bien, dans une coquille +vous pouvez mettre de l'eau, pour la porter ensuite à votre +bouche ; vous pouvez y mettre du sable avant de le verser dans des +bocaux ; en somme, une coquille est un récipient qui permet +de manipuler toutes sortes de contenus. Il en va de même du shell. C'est +un outil en mode texte qui permet l'exploitation d'un grand nombre de +ressources de l'ordinateur. +

+ +

+Cette page vous donnera les rudiments pour exploiter les deux +principales fonctionnalités du shell : +

+ + + + +

Les deux états du shell +

+ +

+Le shell, comme le normalien, ne connaît que deux états : +

+ + + +

+Le shell, une fois lancé, est inactif : il attend qu'on lui donne +des ordres. Quand on lui en donne un, il l'exécute ; et quand il a +terminé, il retourne à son état d'inactivité, en attente d'un nouveau +commandement. +

+ +

+Quand le shell est inactif, il affiche une invite +(prompt en anglais), qui ressemble à cela : +

+ +
+chaland ~ $
+
+ +

+Un curseur, parfois clignotant, indique que le shell attend que vous lui +tapiez des instructions. +

+ +

Comment le shell trouve-t-il les commandes ? +

+ +

L'ordre de recherche

+ +

+J'ai l'habitude de taper des commandes dans le shell, et je vois qu'il +réagit. Mais comment comprend-il ce que je veux faire ? +

+ +

+Prenons un cas simple. Je tape la commande bonjour à +l'invite (prompt) du shell. Il va chercher à plusieurs endroits +ce que j'entends par là : +

+ +
    +
  1. d'abord, il va se demander si bonjour n'est pas une de +ses commandes intégrées ; si c'est le cas, il l'exécute +directement, sinon il passe à l'étape suivante ;
  2. +
  3. ensuite, il va lire le contenu d'une variable, qui s'appelle +PATH, et qui indique le « chemin » où trouver les +commandes que l'on appelle. Par exemple, si la variable PATH contient +les répertoires : + +alors le shell va chercher successivement les commandes : +
  4. +
  5. enfin, s'il ne trouve la commande dans aucun des répertoires +référencés par le PATH, il va renvoyer un message d'erreur +en disant que désolé, il ne voit pas ce que l'on entend par +bonjour. Exemple : + +
    +chaland ~ $ bonjour
    +bonjour: Command not found
  6. +
+ +

La variable PATH consiste en +une liste de répertoires séparés par des +« : ». Si vous voulez voir à quoi ressemble votre +PATH, tapez : +

+ +
+chaland ~ $ echo $PATH
+ + + +

Les commandes internes

+ +

+Certaines commandes du shell ne sont pas des programmes mais des +commandes internes (builtins functions). Comme nous +l'avons vu, elles sont directement reconnues et exécutées par le shell. +Un exemple de commande interne est cd ; elle modifie +le répertoire courant du shell. +

+ +
+

+Attention : si vous créez un script (c'est-à-dire un programme +écrit en langage shell) qui utilise cd, il ne modifie pas +le répertoire courant du shell qui lance ce script, mais celui d'un +shell qui est créé à l'occasion de l'exécution de ce script, et qui +meurt à la fin de cette exécution.

+ +

Exemple : je crée un script aller qui contient les +lignes suivantes :

+ +
+#! /bin/sh
+cd $*
+ +

+Nous aurons alors : +

+ +
+chaland ~ $ aller toto
+chaland ~ $ cd toto
+chaland ~/toto $
+ +
+ + +

Quels programmes utilisent le langage du shell ?

+ +

Les scripts shell

+

+La répétition de commandes complexes en ligne de commande du shell est +rapidement fastidieuse ; aussi est-il très pratique de connaître +les bases de la programmation de scripts shell. Les scripts servent à +automatiser ou systématiser des tâches. +

+ + +

Le script .profile

+

+Il existe un script spécial, qui est exécuté au moment où on se connecte. Ce +script est contenu dans le fichier $HOME/.profile. C'est ce +fichier qui vous dit s'il y a de nouveaux messages dans forum, si vous avez +du courrier, etc. +

+ +

+Ce fichier est normalement mis à jour automatiquement par les scripts de la +config conscrits. Il est néanmoins possible de le modifier pour changer des +options. +

+ +

Le script .xinitrc

+

Il existe encore le script .xinitrc, qui lance X ; +X est le gestionnaire de fenêtres classique sous Unix. +

+ + +

Créer ses propres scripts

+

+Le nombre de scripts possibles est illimité ; vous pouvez en créer +autant que vous voulez, selon vos besoins : c'est ainsi que l'on +personnalise son système et qu'on l'adapte à ses exigences, plutôt que +l'inverse. +

+ + +
+Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien +Doligez. +Modifications : Nicolas George, Baptiste Mélès. +Dernière modification le . +
+ + + diff --git a/unix/shell/script.tml b/unix/shell/script.tml new file mode 100644 index 0000000..0cb139a --- /dev/null +++ b/unix/shell/script.tml @@ -0,0 +1,452 @@ + + + + +Scripts + + + +

Programmation de scripts en shell

+ + +

+Un shell, quel qu'il soit, peut exécuter des commandes prises dans un +fichier. Un fichier contenant des commandes pour le shell est appelé un +script. C'est en fait un programme écrit dans le +langage du shell. Ce langage comprend non seulement les commandes que +nous avons déjà vues, mais aussi des structures de contrôle +(constructions conditionnelles et boucles). +

+ +

+Pour la programmation du shell, nous allons utiliser le shell +sh, qui est le plus répandu et standard. Ce que nous avons +vu jusqu'ici s'applique aussi bien à sh qu'à +zsh et aussi à csh, à l'exception de +setenv et de certaines redirections signalées.

+ + +

Créer un script

+ +

Rendre un script exécutable

+ +

Pour être un script, un fichier doit commencer par la ligne:

+ +
#!/bin/sh
+ +

+Il doit aussi avoir être exécutable (bit x). Le +#!/bin/sh sur la première ligne indique que ce script doit être +exécuté par le shell sh dont on indique le chemin +d'accès. Pour rendre un fichier exécutable, tapez : +

+ +
chaland ~ chmod u+x fichier
+
+ +

+(pour en savoir plus sur les droits attachés à un fichier, consultez la +page sur les droits d'accès). +

+ + +

Le chemin d'une commande

+

+Pour comprendre ce qui suit, vous devez savoir ce qu'est le +PATH. Si ce n'est pas le cas, lisez la page principale sur le shell. +

+ +

+Quand vous exécutez un script, vous pouvez vous trouver à +n'importe quel endroit de l'arborescence de vos répertoires. Si le +répertoire courant ne se situe pas dans votre PATH et +que vous voulez exécuter un programme qui s'y trouve, vous ne pouvez +pas taper : +

+ +
+clipper ~ commande
+
+ +

car si le répertoire courant n'est pas dans le +PATH, le shell n'ira pas y chercher +commande.

+ +

+Vous recevrez donc un message comme : +

+ +
+clipper ~ commande
+zsh: command not found: commande
+ + +

Spécifier le chemin d'une commande

+ +

+Pour que le shell comprenne où chercher votre commande, il faut donc +spécifier l'emplacement de la commande en donnant son chemin, qu'il +soit absolu : +

+ +
+clipper ~ /home/toto/repertoire/courant/commande
+
+ +

ou relatif :

+ +
+clipper ~ repertoire/courant/commande
+
+ +

ou encore sous la forme :

+ +
+clipper ~/repertoire/courant ./commande
+
+ + +

Le répertoire ~/bin

+

+Il y a un certain nombre de commandes que l'on peut vouloir utiliser +depuis n'importe quel répertoire. Dans ce cas, il est fastidieux de : +

+ + + +

Il suffit donc de mettre tous vos scripts dans un même +répertoire, et de mettre ce répertoire dans le +PATH. Par convention, ce répertoire s'appelle +bin et se place dans votre répertoire personnel. Si +votre répertoire personnel est /home/toto, ce +répertoire sera donc /home/toto/bin.

+ +

+Commencez donc par créer ce répertoire : +

+ +
+clipper ~ mkdir bin
+
+ +

+Ensuite, vérifiez qu'il soit bien dans votre PATH : +

+ +
+clipper ~ echo $PATH
+
+ +

Si vous voyez par exemple $HOME/bin +dans votre PATH, alors c'est bon, tous les fichiers +exécutables situés dans ce répertoire seront accessibles depuis +n'importe quel répertoire. +

+ +

+Si ce n'est pas le cas, il faut ajouter ce répertoire au +PATH. Pour cela, ajoutez dans le fichier de configuration +de votre shell, par exemple le fichier .zshrc, la +ligne : +

+ +
PATH=$PATH:$HOME/bin
+ +

Cette ligne indique que la prochaine fois que vous +ouvrirez votre shell, le répertoire bin figurera dans +votre PATH. +

+ +

Principes généraux des scripts shell

+ +

Une succession de commandes

+ +

Si vous manipulez déjà le shell en ligne de commande, vous +pouvez commencer vos premiers scripts. Un script shell est en effet +avant tout une succession de commandes. +

+ +

Par exemple, si vous avez coutume de taper successivement, quand +vous vous loguez à l'ENS : +

+ +
+clipper ~ mozilla &
+clipper ~ mutt
+
+ +

vous pouvez vous créer le script suivant dans le +fichier ~/bin/amorce :

+ +
+#!/bin/sh
+
+mozilla &
+mutt
+
+ +

Ainsi, dès que vous vous connectez, vous pouvez taper +amorce dans le shell, et vos commandes s'exécuteront +automatiquement.

+ + +

Commentaires

+

+Presque tous les langages informatiques autorisent d'insérer des +commentaires ; le shell n'échappe pas à la règle. Pour +cela, il suffit de faire précéder chaque ligne de commentaire du +caractère « # ». Exemple : +

+ +
+#!/bin/sh
+
+# Tout ce que j'écris ici ne sera pas lu.
+echo "Ce que je tape ici sera lu."
+
+ +

+Les lignes blanches ne sont pas interprétées non +plus. N'hésitez donc surtout pas à espacer votre script, les +lignes blanches ne consomment presque rien en termes d'espace disque, ce +n'est donc pas une ressource rare. +

+ +

L'impératif de lisibilité

+ +

+Pourquoi espacer son script ? Pourquoi insérer des +commentaires ? Pour une seule et même raison : +votre script doit être lisible. Pourquoi être +lisible ?

+ +

D'abord, pour autrui : si d'autres gens lisent votre script, il +doit être intelligible, et les passages complexes doivent être +explicités par des commentaires.

+ +

Ensuite, pour vous-même ; au moment où vous écrivez un +script, vous comprenez tout, naturellement ; mais si vous le +relisez dans quelques mois, voire quelques années, les passages +obscurs risqueront d'être incompréhensibles, ce qui est +particulièrement pénible quand on essaye de débuguer +un programme, c'est-à-dire d'en corriger les erreurs. +

+ + +

Structures de contrôle

+ +

+C'est avec les structures de contrôle qu'un programme peut commencer à +devenir sérieux. Le principe général de ces structures est le +suivant : adapter le comportement du programme selon les réponses +apportées à certaines questions. +

+ +

+Nous avons déjà vu une application possible des structures de contrôle +en parlant des variables. Le programme hachoir conçu par +Robert le jardinier pose la question suivante : est-ce que +$USER vaut « Robert » ? +

+ + + + +

La boucle if

+ +

+La structure de contrôle if est la plus courante de toutes, +et la plus élémentaire. Elle est constituée de quatre termes :

+ +
    +
  1. if (si), qui marque la condition à remplir ; +
  2. +
  3. then (alors), qui marque les conséquences si la +condition est remplie ;
  4. +
  5. else (sinon), qui est facultatif et marque le +comportement à adopter si la condition n'est pas remplie ;
  6. +
  7. fi (if à l'envers), qui marque la fin de +la boucle.
  8. +
+ +
if commande ; then commandes ; else commandes ; fi
+ +

ou bien (car le point et virgule équivaut à un saut +de ligne) :

+ +
if commande  
+then commandes 
+else commandes  
+fi
+ +

+Par exemple, pour Robert le jardinier, on aura : +

+ +
if test $USER = Robert
+    then hacher_menu_comme_chair_à_pâté $*
+    else echo "Quand tu seras grand, $USER." 
+         echo "Et fais bien attention en traversant la rue."
+fi
+ + + +

La boucle for

+ +

+La boucle for affecte successivement une variable chaque +chaîne de caractères trouvée dans une liste de chaînes, et +exécute les commandes une fois pour chaque chaîne. +

+ +
for var in liste de chaînes ; do commandes ; done
+ +

ou bien :

+ +
for var in liste de chaînes 
+do commandes 
+done
+ + +

+Rappel : $var accède à la valeur courante de +var. La partie commandes est une suite de commandes, +séparées par des points et virgules (;) ou des retours à la +ligne. +

+ +

+Exemple : +

+ +
for i in *; do echo "$i"; done
+ +

+affiche les noms de tous les fichiers du répertoire courant, un par ligne. +

+ +

+Remarque : plus un programme grossit, plus il importe que son +contenu soit lisible. Les noms de variable doivent donc être le +plus lisibles possible, pour permettre à d'autres gens, ou bien +à vous-même dans quelques mois, de comprendre rapidement votre script. +Ainsi, il peut être plus explicite d'écrire, au lieu de « for +i in *; do echo "$i"; done » : +

+ +
for fichier in *; do echo "$fichier"; done
+ +

+En outre, pour des raisons de lisibilité, n'hésitez pas à +gaspiller des lignes de code en sautant des lignes ; les +lignes de code ne sont pas une ressource rare : +

+ +
for fichier in * 
+do echo "$fichier" 
+done
+ + + +

La boucle while

+ +
while commande  
+do commande  
+done
+ +

+La boucle while exécute les commandes de manière +répétée tant que la première commande réussit.

+ +

Par exemple : tant que le mot de passe correct n'a pas +été donné, refuser l'accès et redemander le mot de passe. +

+ + + + +

La boucle case

+ +
case chaîne in
+  pattern) commande ;;
+  pattern) commande ;;
+esac
+ +

+La boucle case exécute la première commande telle +que la chaîne est de la forme pattern. Un +pattern (motif) est un mot contenant éventuellement les +constructions *, ?, [a-d], avec +la même signification que pour les raccourcis dans les noms de +fichiers. Exemple : +

+ +
+case $var in
+  [0-9]*) echo 'Nombre';;
+  [a-zA-Z]*) echo 'Mot';;
+  *) echo 'Autre chose';;
+esac
+ +

+Vous observerez que l'on clôt la boucle case avec +esac, qui est le mot case à l'envers, de même +que l'on clôt if avec fi. +

+ +

Code de retour

+ +

+On remarque que la condition des commandes if et +while est une commande. Chaque commande renvoie un code de +retour (qui est ignoré en utilisation normale). Si le code est 0, la +commande a réussi ; sinon, la commande a échoué. Par exemple, le +compilateur cc renvoie un code d'erreur non nul si le +fichier compilé contient des erreurs, ou s'il n'existe pas. +

+ +

+Les commandes if et while considèrent donc le +code de retour 0 comme « vrai », et tout autre code comme +« faux ». +

+ +

+Il existe une commande test, qui évalue des expressions +booléennes (c'est-à-dire dont la valeur ne peut être que vraie ou +fausse, 1 ou 0) passées en argument, et renvoie un code de retour en +fonction du résultat. Elle est bien utile pour les scripts. +Exemple : +

+ +
+if test $var = foo
+then echo 'La variable vaut foo'
+else echo 'La variable ne vaut pas foo'
+fi
+ + +

Vous êtes maintenant en mesure de faire ces exercices pour vous +entraîner.

+ + +
+Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez. +Modifications : Nicolas George, Baptiste Mélès. +Dernière modification le . +
+ + + diff --git a/unix/shell/variable.tml b/unix/shell/variable.tml new file mode 100644 index 0000000..6512c92 --- /dev/null +++ b/unix/shell/variable.tml @@ -0,0 +1,225 @@ + + + + +Variables + + + +

Les variables en shell

+ +

Qu'est-ce qu'une variable ?

+ +

+Une variable est l'assignation d'une étiquette à un contenu ; ce +contenu, comme l'indique le mot « variable », peut changer +autant que l'on veut ; l'assignation de l'étiquette à ce contenu, +elle, est fixe, aussi longtemps que l'on ne dissout pas la +variable.

+ +

+La notion de variable est commune à presque tous les langages +informatiques, et en particulier aux langages de programmation. Ceux qui +ont déjà manipulé des langages sont donc familiers avec cette +notion. Pour les autres, un petit exemple les aidera peut-être à la +saisir. +

+ +

+Mettons que vous programmiez un hachoir, comme nous le proposions sur la +page consacrée au shell en ligne de +commande. Un hachoir est un instrument dangereux, à ne pas mettre +à la portée des enfants. Robert le jardinier, qui a conçu ce +hachoir, veut être le seul à pouvoir l'utiliser, sans quoi le +petit Émile pourrait se blesser en y mettant le doigt.

+ +

Ainsi, il va dire au programme hachoir de vérifier la +variable USER, qui contient le nom de l'utilisateur. Si le +nom « Robert » est associé à l'étiquette USER, +alors le programme se met en route ; sinon, il dit à l'utilisateur +de ne pas utiliser cet instrument sans la présence d'un adulte, et de +bien regarder des deux côtés avant de traverser la rue. +

+ +

+Certaines variables sont prédéfinies, par exemple +USER ; mais on peut en créer autant que l'on veut. Par +exemple, si Robert veut autoriser d'autres adultes que lui à utiliser +son hachoir, il peut faire que le programme demande à l'utilisateur quel +âge il a ; la réponse est enregistrée dans la variable +age ; ensuite, le programme va examiner le contenu de +cette variable. Si age >= 18, alors le hachoir peut se +mettre en route ; mais si age < 18, le hachoir +refuse de se mettre en marche. +

+ +

Les variables en shell

+ +

+En shell, pour désigner le contenu d'une variable, on écrit le nom de la +variable précédé du signe dollar. Exemple : echo +$HOME affiche le nom du répertoire personnel de l'utilisateur, +mémorisé par la variable HOME. +

+ +

Les noms de variables

+ +

+Par convention, les variables relevant du système, comme +HOME, USER et beaucoup d'autres, sont en +majuscules, tandis que l'on recommande d'écrire en minuscules les +variables que l'on se crée soi-même. On évite ainsi la désagréable +surprise de remplacer une variable importante et de casser tout ou +partie de son système. +

+ +

+Les noms de variables sont en effet sensibles à la casse : +USER, user, User, +uSeR etc. sont des variables différentes. +

+ + +

Définir une variable

+ +

+La façon de donner une valeur à une variable varie selon le type de shell +utilisé : +

+ +

+C-Shell (csh, tcsh, +lcsh) : on utilise la commande setenv : +

+ +
 
+chaland ~ $ setenv foo bar
+chaland ~ $ echo $foo
+bar
+ +

+Famille des Bourne Shell (sh, bash, +zsh, ksh) : on utilise export : +

+ +
+chaland ~ $ foo=bar
+chaland ~ $ export foo
+chaland ~ $ echo $foo
+bar
+ +
+Comme vous pouvez le remarquer : + + +
+ + +

Les variables d'environnement

+ +

+Les valeurs des variables sont accessibles aux commandes lancées par le +shell. L'ensemble de ces valeurs constitue l'environnement. +On peut aussi supprimer une variable de l'environnement avec +unsetenv (C-Shell) ou unset (Bourne Shell). +

+ +

+Quelques variables d'environnement: +

+ + + +

+Exercice : Assurez-vous que /usr/local/games/bin se trouve +bien dans votre PATH. +

+ +

Utiliser les variables dans un script

+ +

+Dans les scripts, on peut utiliser des variables définies à l'extérieur +(avec setenv ou export), mais aussi définir ses +variables locales propres au script. On donne une valeur à une variable avec +une commande de la forme +nom-de-variable=valeur. Les variables sont +utilisées pour stocker des informations. +

+ +

+On a aussi des variables spéciales, initialisées automatiquement au +début du script: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$0Le nom de la commande (i.e. : du script)
$1, $2, etc.Le premier, deuxième, etc, argument passés au script.
$*La liste de tous les arguments passés au script.
$#Le nombre d'arguments passés au script.
$?Le code de retour de la dernière commande lancée.
$! Le numéro de process de la dernière commande lancée en tâche de fond.
$$Le numéro de process du shell lui-même.
+ + + +
+Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez. +Modifications : Nicolas George, Baptiste Mélès. +Dernière modification le . +
+ + +