500 lines
16 KiB
XML
500 lines
16 KiB
XML
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||
<!DOCTYPE html
|
||
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
|
||
"tuteurs://DTD/tml.dtd">
|
||
<html>
|
||
<head>
|
||
<title>Commandes</title>
|
||
</head>
|
||
<body>
|
||
|
||
<h1>Le shell en ligne de commande</h1>
|
||
|
||
<h2>Créer des processus</h2>
|
||
|
||
<p> 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.
|
||
</p>
|
||
|
||
<h3>Qu'est-ce qu'un processus ?</h3>
|
||
|
||
<p> Lancer un programme, c'est créer un
|
||
<em>processus</em>. Tautologisons : <strong>un processus est une
|
||
instance d'exécution d'un programme</strong>, c'est-à-dire
|
||
l'exécution particulière d'un programme universel (<i>i.e</i> qui
|
||
n'est pas réductible à l'une de ses exécutions). </p>
|
||
|
||
<p>Par exemple, si je lance Mozilla, un processus se crée, du nom de
|
||
<code>mozilla</code>. Ensuite, sans fermer ce programme, je lance une
|
||
deuxième fois Mozilla ; un nouveau processus se crée, du nom
|
||
de <code>mozilla</code> é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.
|
||
</p>
|
||
|
||
<h3>Généalogie des processus</h3>
|
||
|
||
<p> Dans notre exemple, nous avons deux processus
|
||
<code>mozilla</code>. 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.
|
||
</p>
|
||
|
||
<p> Toutefois, s'ils sont indépendants l'un de l'autre, tous deux
|
||
dépendent du processus qui les a lancés. Eh oui, <strong>le shell
|
||
est un programme comme un autre, donc chacune de ses exécutions
|
||
correspond également à la création d'un processus</strong>. Si
|
||
vous lancez trois shells en même temps, par exemple dans trois
|
||
terminaux différents, vous aurez trois processus <code>shell</code>
|
||
distincts. </p>
|
||
|
||
<p>
|
||
Les processus entretiennent entre eux des relations de parenté. Mais
|
||
comme les processus ont tous le même sexe, <strong>chaque processus
|
||
n'a qu'un parent. Un processus peut avoir plusieurs enfants</strong>.
|
||
</p>
|
||
|
||
<p> Le shell est, comme nous venons de le voir, <strong>un processus qui
|
||
peut enfanter d'autres processus</strong>. Par exemple, à chaque fois
|
||
que je tape <code>mozilla</code>, mon shell crée un processus
|
||
<code>mozilla</code>. </p>
|
||
|
||
|
||
<h3>Lancer des processus en arrière-plan</h3>
|
||
<p>
|
||
<strong>Par défaut, le shell met le processus enfant en
|
||
avant-plan</strong>. Cela veut dire que si je tape simplement :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~</span> mozilla
|
||
</pre>
|
||
|
||
<p class="continue">
|
||
le processus <code>mozilla</code> 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
|
||
<code>mozilla</code> prend fin (si je ferme ce programme, par exemple)
|
||
que le shell reprend la main.
|
||
</p>
|
||
|
||
<p>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. </p>
|
||
|
||
<p>Il faudrait donc que l'on puisse <strong>lancer des processus enfants en
|
||
arrière-plan</strong>, de telle sorte que ces processus se lancent
|
||
dans leur propre fenêtre et me permettent toutefois de dialoguer avec
|
||
le shell sans avoir à :</p>
|
||
<ul>
|
||
<li> ouvrir un nouveau shell dans une nouvelle fenêtre ;</li>
|
||
<li> attendre la fin de l'un de ces processus.</li>
|
||
</ul>
|
||
|
||
<p>Pour cela, il faut ajouter le signe « & » à la
|
||
fin d'une ligne de commande. On peut ainsi taper :</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~</span> mozilla &
|
||
<span class="prompt">chaland ~</span> mozilla &
|
||
<span class="prompt">chaland ~</span>
|
||
</pre>
|
||
|
||
<p class="continue">et de la sorte, un même shell peut engendrer
|
||
autant de processus que vous voulez.</p>
|
||
|
||
|
||
<h3>Émanciper un processus enfant</h3>
|
||
<p>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, <strong>la mort d'un processus parent entraîne celle de
|
||
tous ses enfants</strong>. Par exemple, si le shell qui a enfanté les
|
||
deux processus <code>mozilla</code> vient à décéder (si je le
|
||
ferme brutalement, ou s'il plante), les deux processus
|
||
<code>mozilla</code> le suivront dans la mort. </p>
|
||
|
||
<p>
|
||
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 :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~</span> mozilla &!
|
||
<span class="prompt">chaland ~</span> mozilla &!
|
||
<span class="prompt">chaland ~</span>
|
||
</pre>
|
||
|
||
<p class="continue">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 <code>mozilla</code>. </p>
|
||
|
||
|
||
<h2>Arguments et options</h2>
|
||
<p> Jusqu'ici, l'exemple de processus enfant que nous avons pris
|
||
était relativement simple : il s'agissait de la commande
|
||
<code>mozilla</code>, que l'on peut lancer en tapant simplement son
|
||
nom. </p>
|
||
|
||
<p>
|
||
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 ?
|
||
</p>
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
|
||
<h3>Les arguments</h3>
|
||
<p>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. </p>
|
||
|
||
|
||
<h4>Exemples</h4>
|
||
|
||
<p>Par exemple, si je veux ouvrir le fichier <code>hermocrate.txt</code>
|
||
avec l'éditeur de texte <code>nano</code>, j'ai le choix entre deux
|
||
possibilités :</p>
|
||
|
||
<ul>
|
||
<li> ou bien je tape :
|
||
<pre><span class="prompt">chaland ~</span> nano </pre>
|
||
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
|
||
<code>hermocrate.txt</code> — mais tout cela est bien
|
||
fastidieux ; </li>
|
||
|
||
<li> ou bien je tape directement :
|
||
<pre><span class="prompt">chaland ~</span> nano hermocrate.txt</pre>
|
||
</li>
|
||
</ul>
|
||
|
||
<p>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 :</p>
|
||
|
||
<pre><span class="prompt">chaland ~</span> mozilla http://www.tuteurs.ens.fr/</pre>
|
||
|
||
<h3>Les options</h3>
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<p>Sous Unix, les options commencent généralement par un
|
||
tiret. Certaines options peuvent à leur tour prendre des
|
||
arguments.</p>
|
||
|
||
<p>Par exemple, si l'on veut ouvrir un fichier au format MS-DOS, on peut
|
||
taper :</p>
|
||
|
||
<pre><span class="prompt">chaland ~</span> nano -D hermocrate.txt</pre>
|
||
|
||
|
||
<h4>Options à arguments</h4>
|
||
|
||
<p>
|
||
L'option <code>-r</code> de <code>nano</code> 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 :
|
||
</p>
|
||
|
||
<pre><span class="prompt">chaland ~</span> nano -r 75 hermocrate.txt</pre>
|
||
|
||
|
||
<h4>Options à nom long</h4>
|
||
|
||
<p>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 :</p>
|
||
|
||
<pre><span class="prompt">chaland ~</span> nano --fill=75 hermocrate.txt</pre>
|
||
|
||
<p class="continue">Dans cet exemple, il se trouve que l'option à nom
|
||
long <code>--fill=</code> équivaut à l'option à nom
|
||
court <code>-r</code>. Mais toutes les commandes courtes n'ont pas
|
||
systématiquement leur équivalent à nom long, et vice versa.</p>
|
||
|
||
<h2>Jokers et citations</h2>
|
||
|
||
<h3><a name="raccourcis">Raccourcis pour les noms de fichiers : les
|
||
jokers</a></h3>
|
||
|
||
<p>
|
||
Il est souvent ennuyeux d'avoir à taper une longue liste de fichiers
|
||
pour les donner en arguments à une commande, comme :
|
||
</p>
|
||
|
||
<pre>cc -o foo bar.c gee.c buz.c gog.c</pre>
|
||
|
||
<p>
|
||
Pour éviter ces problèmes, on peut utiliser des <em>jokers</em>
|
||
(<em>wildcards</em> 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.
|
||
</p>
|
||
|
||
<p>
|
||
Il existe principalement trois types de jokers :
|
||
</p>
|
||
|
||
<ul>
|
||
<li> l'étoile (*), qui remplace n'importe quelle séquence de
|
||
caractères ;</li>
|
||
<li> le point d'interrogation, qui remplace n'importe quel
|
||
caractère ;</li>
|
||
<li> les crochets ([]), qui remplacent n'importe quel caractère d'une
|
||
liste déterminée.</li>
|
||
</ul>
|
||
|
||
<h4>L'étoile : *</h4>
|
||
|
||
<p>
|
||
Une <strong>étoile</strong> <code>*</code> 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 :
|
||
</p>
|
||
|
||
<pre>cc -o foo *.c</pre>
|
||
|
||
<p>
|
||
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 <code>.</code> et
|
||
qui finissent par <code>.c</code>. Ensuite, il remplace <code>*.c</code>
|
||
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 :
|
||
</p>
|
||
|
||
<pre>cc -o foo bar.c buz.c foo.c gee.c gog.c</pre>
|
||
|
||
<h4>Le point d'interrogation : ?</h4>
|
||
|
||
<p>
|
||
On a aussi le <strong>point d'interrogation</strong> <code>?</code>, qui
|
||
remplace un (et exactement un) caractère quelconque (sauf un point en début
|
||
de nom). Par exemple, <code>ls *.?</code> liste tous les dont l'extension
|
||
ne comporte qu'un caractère (<code>.c</code>, <code>.h</code>...).
|
||
</p>
|
||
|
||
<h4>Les crochets : []</h4>
|
||
|
||
<p>
|
||
La forme <code>[abcd]</code> remplace un caractère quelconque parmi
|
||
<code>a</code>, <code>b</code>, <code>c</code>, <code>d</code>. Enfin,
|
||
<code>[^abcd]</code> remplace un
|
||
caractère quelconque qui ne se trouve pas parmi <code>a</code>, <code>b</code>,
|
||
<code>c</code>, <code>d</code>.
|
||
</p>
|
||
|
||
<h4>Exemple</h4>
|
||
|
||
<pre>echo /users/*</pre>
|
||
|
||
<p class="continue">
|
||
affiche à peu près la même chose que
|
||
</p>
|
||
|
||
<pre>ls /users</pre>
|
||
|
||
<p class="continue">
|
||
(La commande <code>echo</code> se contente d'afficher ses arguments.)
|
||
</p>
|
||
|
||
<div class="attention">
|
||
<p>
|
||
&icone.attention; Attention :
|
||
</p>
|
||
|
||
<ul>
|
||
|
||
<li><strong>C'est le shell qui fait le remplacement des arguments
|
||
contenant un joker</strong>. On ne peut donc pas faire <code>mv *.c
|
||
*.bak</code>, car le shell va passer à <code>mv</code> les arguments
|
||
<code>foo.c bar.c foo.bak bar.bak</code>, et <code>mv</code> ne sait pas
|
||
quel fichier remplacer. </li>
|
||
|
||
<li> <strong>Attention aux espaces</strong>. Si vous tapez <code>rm *
|
||
~</code>, le shell remplace l'étoile par la liste des fichiers présents,
|
||
et ils seront tous effacés. Si vous tapez <code>rm *~</code>, seuls les
|
||
fichiers dont le nom finit par un tilde seront effacés. </li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="encadre">
|
||
<p>
|
||
<strong>Interlude :</strong> comment effacer un fichier nommé
|
||
<code>?*</code> ? On ne peut pas taper <code>rm ?*</code> car le shell
|
||
remplace <code>?*</code> par la liste de tous les fichiers du répertoire
|
||
courant. On peut taper <code>rm -i *</code> qui supprime tous les
|
||
fichiers, mais en demandant confirmation à chaque fichier. On répond
|
||
<code>n</code> à toutes les questions sauf <code>rm: remove ?*</code>.
|
||
Autre méthode: utiliser les mécanismes de citation.
|
||
</p>
|
||
</div>
|
||
|
||
<h3><a name="quotation">Contourner les jokers : la citation (<i
|
||
lang="en">quotation</i>)</a></h3>
|
||
|
||
<p>
|
||
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
|
||
<code>echo</code> ?</p>
|
||
|
||
<p>
|
||
On ne peut pas les taper directement dans la ligne de commande (ici,
|
||
avec le shell <code>zsh</code>), car le shell essaye de les interpréter
|
||
comme des jokers :
|
||
</p>
|
||
|
||
<pre><span class="prompt">chaland ~</span> echo ?*$
|
||
zsh: no matches found: ?*$</pre>
|
||
|
||
<p> 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 <i lang="en">quotations</i> (mot anglais
|
||
signifiant <em>citation</em>).
|
||
</p>
|
||
|
||
<p>
|
||
Les mécanismes de citation sont les suivants :
|
||
</p>
|
||
|
||
<ul>
|
||
<li> le backslash (<code>\</code>), qui protège un caractère de
|
||
l'interprétation par le shell ;</li>
|
||
<li> les apostrophes ou <i lang="en">simple quotes</i>
|
||
(<code>'</code>), qui protègent une chaîne de caractères de
|
||
l'interprétation par le shell ;</li>
|
||
<li> les guillemets doubles ou <i lang="en">double quotes</i>
|
||
(<code>"</code>), 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 ;</li>
|
||
<li> les <i lang="en">backquotes</i> (<code>`</code>), qui cite la
|
||
sortie d'une commande.</li>
|
||
</ul>
|
||
|
||
|
||
|
||
<h4>Le backslash (<code>\</code>)</h4>
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<p>
|
||
Exemples :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~ $</span> echo \?\*\$
|
||
?*$
|
||
<span class="prompt">chaland ~ $</span> echo \\\?\\\*\\\$
|
||
\?\*\$</pre>
|
||
|
||
<h4>Les apostrophes ou simples quotes (<code>'</code>)</h4>
|
||
|
||
<p>
|
||
Un autre moyen est d'inclure une chaîne de caractères entre apostrophes
|
||
(simples quotes) <code>'</code>. Tout ce qui se trouve entre deux
|
||
apostrophes sera passé tel quel par le shell à la
|
||
commande. Exemple :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~ $</span> echo '$?*'
|
||
$?*</pre>
|
||
|
||
<h4>Les guillemets doubles ou doubles quotes (<code>"</code>)</h4>
|
||
|
||
<p>
|
||
Les guillemets se comportent comme les apostrophes, à une exception près: les
|
||
dollars et les backslashes sont interprétés entre les guillemets.
|
||
Exemple :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~ $</span> echo "$HOME/*"
|
||
/users/87/maths/doligez/*</pre>
|
||
|
||
<p>
|
||
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 :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~ $</span> echo "'"'"'
|
||
'"</pre>
|
||
|
||
<p>
|
||
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
|
||
<code>echo</code> est bien utile dans ce cas.
|
||
</p>
|
||
|
||
<h4>Les backquotes (<code>`</code>)</h4>
|
||
|
||
<p>
|
||
Dernière forme de citation : <code>`<em>commande</em>`</code>. Le
|
||
shell exécute la <em>commande</em> indiquée entre backquotes, lit la
|
||
sortie de la commande mot par mot, et remplace <code>`</code>
|
||
<em>commande</em> <code>`</code> par la liste de ces mots.
|
||
Exemple :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~ $</span> echo `ls`
|
||
Mail News bin foo lib misc mur notes.aux notes.dvi notes.log
|
||
notes.tex planar text
|
||
<span class="prompt">chaland ~ $</span> ls -l `which emacs`
|
||
-rwxr-xr-t 1 root taff 978944 Jul 16 1991 /usr/local/bin/emacs</pre>
|
||
|
||
<p>
|
||
La commande <code>which <em>cmd</em></code> employée ci-dessus affiche sur sa
|
||
sortie le nom absolu du fichier exécuté par le shell quand on lance la
|
||
commande it <em>cmd</em> :
|
||
</p>
|
||
|
||
<pre>
|
||
<span class="prompt">chaland ~ $</span> which emacs
|
||
/usr/local/bin/emacs</pre>
|
||
|
||
|
||
|
||
<p>Vous êtes maintenant en mesure de faire ces <a
|
||
href="&url.tuteurs;unix/exercices/">exercices</a> pour vous
|
||
entraîner.</p>
|
||
|
||
|
||
<div class="metainformation">
|
||
Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez.
|
||
Modifications : Nicolas George, Baptiste Mélès.
|
||
Dernière modification le <date value="$Date: 2005-05-31 11:33:37 $" />.
|
||
</div>
|
||
|
||
</body>
|
||
</html>
|