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 @@ + + + +
+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. +
+ +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.
+
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
.
+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.
+ + +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
.
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. +
+ + +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.
+ + +Par exemple, si je veux ouvrir le fichier hermocrate.txt
+avec l'éditeur de texte nano
, j'ai le choix entre deux
+possibilités :
chaland ~ nano
+puis Ctrl-R pour indiquer d'ouvrir un fichier, puis Ctrl-T
+pour voir la liste des fichiers, puis les flèches pour choisir mes
+fichiers, enfin Entrée pour sélectionner
+hermocrate.txt
— mais tout cela est bien
+fastidieux ; chaland ~ nano hermocrate.txt
+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 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
+
+
+
+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
+
+
+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.
+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 : +
+ +
+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+ +
+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
...).
+
+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
.
+
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 : +
+ +mv *.c
+*.bak
, car le shell va passer à mv
les arguments
+foo.c bar.c foo.bak bar.bak
, et mv
ne sait pas
+quel fichier remplacer. rm *
+~
, le shell remplace l'étoile par la liste des fichiers présents,
+et ils seront tous effacés. Si vous tapez rm *~
, seuls les
+fichiers dont le nom finit par un tilde seront effacés.
+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.
+
+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 : +
+ +\
), qui protège un caractère de
+l'interprétation par le shell ;'
), qui protègent une chaîne de caractères de
+l'interprétation par le shell ;"
), qui protègent également une chaîne de caractères
+de l'interprétation par le shell, mais avec plus de souplesse que les
+précédents ;`
), qui cite la
+sortie d'une commande.\
)+ 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 \\\?\\\*\\\$ +\?\*\$+ +
'
)
+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 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.
+
`
)
+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.
+ + + + + + 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 @@ + + + + ++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. +
+ ++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. +
+ + + + ++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. +
+ ++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. +
+ + +>
+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.
+
>>
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.
+
<
+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.
+
|
+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. +
+ + + +
+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.
+
+
+
+
+
+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 suivante | +2>&1 | |
+ |& |
+
Redirige la sortie d'erreur et la sortie standard dans un fichier | +2>&1 > |
+ >& |
+
Redirige la sortie d'erreur et la sortie +standard à la fin d'un fichier existant | +2>&1 >> |
+>>& |
+
+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:
+
less
,
+bien plus évolué) à la fin du pipe-line, affiche le résultat page par page,
+pour laisser le temps de le lire.
+fold
coupe les lignes de son
+entrée à 80 caractères et écrit le résultat sur sa sortie.
+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
.
+
+La panoplie complète des redirections est la suivante : +
+ +>
: change la sortie standard de la commande pour la placer
+dans un fichier.
+<
: change l'entrée standard de la commande pour la prendre
+dans un fichier.
+|
: branche la sortie standard de la commande de gauche sur
+l'entrée standard de la commande de droite.
+>>
: change la sortie standard pour l'ajouter à la fin
+d'un fichier existant.
+||
: exécuter la commande suivante si la première a
+échoué.
+&&
: n'exécuter la commande suivante que si la
+première a réussi.
+Vous êtes maintenant en mesure de faire ces exercices pour vous +entraîner.
+ + + + + + 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 @@ + + + + +
+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 : +
+ ++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. +
+ ++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à :
+
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 ;PATH
, et qui indique le « chemin » où trouver les
+commandes que l'on appelle. Par exemple, si la variable PATH contient
+les répertoires :
+/usr/bin
/bin
et /home/toto/bin
,/usr/bin/bonjour
,/bin/bonjour
et /home/toto/bin/bonjour
;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
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
+
+
+
+
+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 $+ +
+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. +
+ + +.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. +
+ +.xinitrc
Il existe encore le script .xinitrc
, qui lance X ;
+X est le gestionnaire de fenêtres classique sous Unix.
+
+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. +
+ + + + + + 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 @@ + + + + ++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.
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). +
+ + +
+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
+
+
++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
+
+
+
+~/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
.
+
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.
+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. +
+ ++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. +
+ + ++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 » ?
+
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 :
if
(si), qui marque la condition à remplir ;
+then
(alors), qui marque les conséquences si la
+condition est remplie ; else
(sinon), qui est facultatif et marque le
+comportement à adopter si la condition n'est pas remplie ; fi
(if
à l'envers), qui marque la fin de
+la boucle.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+ + + +
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+ + + +
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. +
+ + + + +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
.
+
+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.
+ + + + + + 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 @@ + + + + ++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.
+
+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
.
+
+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.
+
+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+ +
+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: +
+ +DISPLAY
: L'écran sur lequel les programmes X
+travaillent. Cette variable est souvent de la forme :
+machine.somehost.somewhere:0.0
Si cette variable est vide,
+c'est qu'il n'y a pas d'affichage graphique possible. PRINTER
: pour les commandes d'impression. Contient le
+nom de l'imprimante sur laquelle il faut envoyer vos fichiers. EDITOR
: utilisée par mutt
,
+forum
, et beaucoup d'autres commandes. Contient le nom de
+votre éditeur de textes préféré. VISUAL
: la même chose qu'EDITOR
. SHELL
: contient le nom de votre shell. HOME
: contient le nom de votre répertoire personnel.
+USER
: contient votre nom de login. LOGNAME
: la même chose que USER
. PATH
: contient une liste de répertoires dans lesquels
+le shell va chercher les commandes.
+
+Exercice : Assurez-vous que /usr/local/games/bin
se trouve
+bien dans votre PATH.
+
+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: +
+ +$0 |
+Le 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. | +