tuteurs.ens.fr/unix/exercices/solutions/systeme-sol.tml

711 lines
16 KiB
Text
Raw Normal View History

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
"tuteurs://DTD/tml.dtd">
<html>
<head>
<title>Syst<73>me</title>
</head>
<body>
<h1>Solutions des exercices sur le syst<73>me</h1>
<h2><a name="droits">Les droits </a> </h2>
<ol>
<li><strong> <a name="droits1">
Changez les droits d'un fichier <tt>fic1</tt> pour que tous ceux de votre
groupe puissent <20>crire dedans.</a></strong>
<pre>
chmod g+w fic1
</pre>
</li>
<li><strong> <a name="droits2">
Donnez en une seule ligne le droit d'ex<65>cution <20> tous les utilisateurs d'un
fichier <tt>script</tt> qui n'a jusqu'alors que des droits standards
(<tt>-rw-r--r--</tt>).</a></strong>
<pre>
chmod uog+x script
</pre></li>
<li><strong> <a name="droits3">
Le fichier <tt>toto</tt> a les droits suivants&nbsp;: <tt>-rwxr--r--</tt>.
Modifiez-en les droits en une ligne de commande de sorte que le
propri<EFBFBD>taire n'ait plus que le droit de lecture.</a></strong>
<pre>
chmod u-wx toto
</pre></li>
<li><strong> <a name="droits4">
Modifier les droits du fichier <tt>toto</tt> (<tt>-rwxr--r--</tt>) de sorte
que le groupe et les autres utilisateurs aient les m<>mes droits que le
propri<EFBFBD>taire.</a></strong>
<pre>
chmod og+wx toto
</pre></li>
<li><strong> <a name="droits5">
Quelle option permet de modifier r<>cursivement les droits d'un r<>pertoire
et des fichiers qu'il contient&nbsp;?</a></strong>
<p>
C'est l'option <code>-R</code>. Par exemple, pour interdire tous les
droits aux fichiers pr<70>sents dans une branche du r<>pertoire
<code>confidentiel</code>, on peut faire&nbsp;:
</p>
<pre>
chmod -R og-rwx confidentiel
</pre></li>
<li><strong> <a name="droits6">
Quelle option de <tt>mkdir</tt> permet de cr<63>er un r<>pertoire en sp<73>cifiant
les droits sur ce r<>pertoire&nbsp;?</a></strong>
<p>
C'est l'option <code>-m</code> qui permet de le faire. Par exemple, pour
cr<EFBFBD>er un r<>pertoire en lecture interdite aux autres&nbsp;:
</p>
<pre>
mkdir -m og-r repertoire
</pre></li>
<li><strong> <a name="droits7">
Affichez et interpr<70>tez les droits de <tt>/usr/sbin/mount</tt>.
</a></strong>
<pre>
<span class="prompt">bireme ~ $</span>&nbsp;ll /usr/sbin/mount
-r-xr-xr-x 1 root bin 27208 Jan 9 2000 /usr/sbin/mount*
</pre>
Il s'agit d'un fichier <20>x<EFBFBD>cutable par tout utilisateur.</li>
</ol>
<h2><a name="liens"> Les liens</a> </h2>
<!-- #################################&nbsp;!-->
<ol>
<li><strong> <a name="liens1">
Vous avez chez vous un r<>pertoire <tt>tmp/</tt> qui contient un fichier
<tt>bidon</tt>. Cr<43>ez un lien physique sur <tt>tmp/bidon</tt> appel<65>
<tt>blo</tt>, dans votre r<>pertoire d'accueil (<tt>HOME</tt>). Comparez
les contenus de <tt>tmp/bidon</tt> et de <tt>blo</tt>. Que contient
<tt>blo</tt>&nbsp;?</a></strong>
<pre>
ln tmp/bidon blo
</pre>
Les contenus sont identiques. Les noms de fichiers <code>tmp/bidon</code>
et <code>blo</code> renvoient au m<>me endroit sur le disque dur.
</li>
<li><strong> <a name="liens2">
M<EFBFBD>me question avec un lien symbolique.</a></strong>
<pre>
ln -s tmp/bidon blo
</pre>
Le contenu <em>semble</em> <20>tre identique, cependant, <20> propos du
<code>blo</code>, le disque dur ne contient comme information que le nom
du fichier vers lequel le lien pointe (<code>tmp/bidon</code>).
</li>
<li><strong> <a name="liens3">
Quelles sont les diff<66>rences entre les liens durs et les liens
symboliques&nbsp;?</a></strong>
<p> On vient d'en voir une. On en d<>duit que le temps d'acc<63>s au contenu
d'un lien dur est plus rapide que pour un lien symbolique. Une autre
diff<EFBFBD>rence notable est que, contrairement aux liens symboliques, un lien
dur ne peut pas pointer vers un r<>pertoire. </p>
</li>
<li><strong> <a name="liens4">
Dans quel cas ne peut-on pas faire de lien physique&nbsp;? Que faut-il
faire&nbsp;?</a></strong>
<p>On ne peut pas faire de lien dur vers un r<>pertoire. Dans ce cas, il faut
donc utiliser un lien symbolique.</p>
</li>
<li><strong> <a name="liens5">
Quel est l'effet de <tt>chmod</tt> sur un lien&nbsp;?</a></strong>
<p>
S'il s'agit d'un lien dur, les droits des <em>deux</em> fichiers li<6C>s
sont modifi<66>s. En revanche, s'il s'agit d'un lien symbolique, les deux
fichiers peuvent avoir des droits diff<66>rents.
</p>
</li>
</ol>
<h2><a name="processus"> Les processus </a></h2>
<ol>
<li><strong> <a name="processus1">
Affichez la liste des processus associ<63>s <20> votre terminal. Affichez la
liste des processus dont vous <20>tes propri<72>taire. Recommencez en utilisant
l'option <tt>-l</tt>. <20> quoi correspondent les colonnes
<tt>PID</tt> et <tt>PPID</tt>&nbsp;?</a></strong>
<pre>
<span class="prompt">bireme ~ $</span>&nbsp;ps
PID TT S TIME COMMAND
16970 pts/2 S 0:00 /usr/local/util/bin/zsh4
16992 pts/2 S 0:07 vim systeme-sol.tml
17382 pts/3 R 0:00 /usr/local/util/bin/zsh4
<span class="prompt">bireme ~ $</span>&nbsp;ps -l
F UID PID PPID %C PRI NI SZ RSS WCHAN S TT TIME COMMAND
8 9625 16970 16967 0 48 20 4032 3152 mutex_ex S pts/2 0:00 /usr/local/u
8 9625 16992 16970 1 58 20 4312 3760 mutex_ex S pts/2 0:07 vim systeme-
8 9625 17382 17379 0 48 20 3912 2840 mutex_ex S pts/3 0:00 /usr/local/u
</pre>
<p>Les num<75>ros apparaissant dans la colonne <tt>PID</tt> sont les num<75>ros
des diff<66>rents processus. Le <tt>PPID</tt> d<>signe lui le num<75>ro du
processus p<>re du processus en question. Par exemple, ici, le processus
16992 (<tt>vim</tt>) est un fils du processus 16970 (<tt>zsh</tt>).
</p>
</li>
<li><strong> <a name="processus2">
Lancez une commande longue en arri<72>re plan. Quel est le comportement du
processus associ<63> lorsqu'il re<72>oit les signaux suivants&nbsp;:</a></strong>
<p>
Pour envoyer un signal <20> un processus, on peut faire&nbsp;:
</p>
<pre>
<span class="prompt">bireme ~ $</span>&nbsp;kill -23 17382
</pre>
<p class="continue">
17382 d<>signant un num<75>ro de processus (PID) et 23 le num<75>ro d'un signal
(SIGSTOP).
</p>
<ul>
<li> <tt>sigkill</tt> (9)
<p>Le processus est tu<74> sans pouvoir de d<>fendre.</p></li>
<li> <tt>sigstop</tt> (23)
<p>
Le processus s'interrompt.
</p></li>
<li> <tt>sigcont</tt> (25)
<p>
Le processus interrompu red<65>marre.
</p></li>
</ul></li>
<li><strong> <a name="processus3">
Utilisez la commande <tt>nice</tt> pour lancer des commandes ayant une
faible priorit<69>.</a></strong>
<pre>
<span class="prompt">bireme ~ $</span>&nbsp;nice -19 ./calcul
</pre>
</li>
<li><strong> <a name="processus4">
Interpr<EFBFBD>tez la hi<68>rarchie des processus qui vous appartiennent.
</a></strong>
<p> Pour vous aider <20> comprendre, vous pouvez afficher un arbre en
lan<EFBFBD>ant la commande <tt>pstree</tt> (FreeBSD) ou <tt>ptree</tt>
(Solaris). </p>
</li>
<li><strong> <a name="processus5">
La commande <tt>ps | wc</tt> compte deux processus en plus de ceux qui
existent r<>ellement lorsqu'on lance la commande. Pourquoi&nbsp;?</a></strong>
<p>
Ce sont les processus associ<63>s aux commandes <tt>ps</tt> et <tt>wc</tt>
que vous venez de lancer&nbsp;!
</p>
</li>
<li><strong> <a name="processus6">
Donner deux commandes pour reprendre l'ex<65>cution d'une instruction
interrompue par un <tt>^Z</tt>.</a></strong>
<p>
Vous disposez des commandes <tt>fg</tt> et <tt>bg</tt>. <tt>fg</tt>
permet de poursuivre le d<>roulement du programme. <tt>bg</tt> le fait
aussi mais il relance le programme <em>en t<>che de fond</em>.
</p>
</li>
</ol>
<h2><a name="shell">Programmation du shell</a></h2>
<ol>
<li><strong> <a name="shell2">
Faites deux scripts qui vous disent bonjour en affichant votre login
(<28>Bonjour, toto<74>)&nbsp;:</a></strong>
<ul>
<li> Quand vous tapez <tt>saluer [votre-login]</tt></li>
<li> Quand vous tapez juste <tt>saluer</tt></li>
</ul>
<p>
Il faut <20>diter un fichier <tt>saluer</tt> et le rendre ensuite
<EFBFBD>x<EFBFBD>cutable&nbsp;:</p>
<pre>
#!/bin/sh
if [ -n "$1" ]; then LOGIN=$1; else LOGIN=`whoami`; fi
echo "Bonjour, $LOGIN"
</pre>
</li>
<li><strong> <a name="shell4">
Faire un script qui affiche la phrase&nbsp;: <tt>Le script [params] a [n]
param<EFBFBD>tre(s), que voici&nbsp;: [param<61>tres]</tt>, en rempla<6C>ant les mots entre
crochets par leur valeur; par exemple&nbsp;:</a></strong>
<pre>
<span class="prompt">chaland ~ $</span>&nbsp;params bla ble bli blo blu
La commande params a 5 param<61>tre(s), que voici&nbsp;: bla ble bli blo blu
</pre>
<pre>
#!/bin/sh
echo "La commande $0 a $# param<61>tre(s), que voici| : $@"
</pre>
</li>
<li><strong> <a name="shell5">
Cr<EFBFBD>ez une commande qui, lorsqu'elle est appel<65>e, renvoie le nombre
d'arguments qui lui ont <20>t<EFBFBD> fournis, ainsi que le premier de ces
arguments.</a></strong>
<pre>
#!/bin/sh
echo "J'ai re<72>u $# arguments"
echo "Le premier d'iceux est $1"
</pre>
</li>
<li><strong> <a name="shell6">
Vous voulez <20>crire un script qui vous dit combien de personnes sont logu<67>es
sur une machine donn<6E>e; par exemple&nbsp;: </a></strong>
<pre>
<span class="prompt">drakkar ~ $</span>&nbsp;combien galion
Il y a 5 personne(s) logu<67>es sur galion en ce moment.
<span class="prompt">drakkar ~ $</span>
</pre>
<pre>
#!/bin/sh
N=`who | wc -l | sed -e "s/ *//"`
MACHINE=`whoami`
echo "Il y a $N personne(s) logu<67>s sur $MACHINE en ce moment"
</pre>
</li>
<li><strong> <a name="shell7">
On veut remplacer
le suffixe <tt>.htm</tt> d'un ensemble de fichiers en
<tt>.html</tt>.</a></strong>
<p>
Le script suivant lanc<6E> avec "**/*.htm" comme param<61>tre devrait
fonctionner&nbsp;:
</p>
<pre>
#!/bin/sh
for i in $@;
do
mv $i `echo $i | sed -e "s/htm$/html/"`
done;
</pre>
</li>
<li><strong> <a name="shell8"> Un ensemble de noms de fichiers sont en
majuscules. On veut tout basculer en minuscules.</a></strong>
<pre>
#!/bin/sh
for i in $@;
do
mv $i `echo $i | tr '[:upper:]' '[:lower:]'`
done;
</pre>
</li>
<li><strong> <a name="shell9">
Cr<EFBFBD>ez un script <tt>indice</tt> qui affiche l'indice de son premier
argument dans la liste des arguments suivants. Par exemple, </a></strong>
<pre>
indice toto tata titi toto tutu
</pre>
<p>
renvoie l'indice de <tt>toto</tt> dans la liste <tt>tata titi toto
tutu</tt>, c'est-<2D>-dire 3.</p>
<pre>
#!/bin/sh
ARG=$1
shift
N=0
for i in $@;
do
N=`expr $N + 1`
[ x$ARG = x$i ] &amp;&amp; echo $N
done;
</pre>
</li>
<li><strong> <a name="shell10">
On ne s'int<6E>resse ici qu'<27> des fichiers contenant un mot par ligne. <20>crire
un script qui compte le nombre de mots contenant une des lettres <20>r<EFBFBD>, <20>s<EFBFBD>
ou <20>t<EFBFBD>, et parmi eux, ceux qui ont au moins deux telles lettres. On
donnera aussi le nombre de mots ne contenant aucune voyelle. Cela donnera
par exemple&nbsp;:</a></strong>
<pre>
Dans ce fichier, vous avez&nbsp;:
45 mots contenant <20>r<EFBFBD>, <20>s<EFBFBD> ou <20>t<EFBFBD>, et parmi eux,
12 contiennent deux de ces lettres au moins.
Il y a aussi 10 mots ne contenant aucune voyelle.
</pre>
<pre>
#!/bin/sh
RST=`grep "[rst]" $1 | wc -l`
DEUX=`grep "[rst].*[rst]" $1 | wc -l`
CONS=`grep -v "[aeiou]" $1 | wc -l`
(echo "Dans ce fichier, vous avez| :";
echo "$RST mots contenant <20>r<EFBFBD>, <20>s<EFBFBD> ou <20>t<EFBFBD> et parmi eux,";
echo "$DEUX contiennent deux de ces lettres au moins.";
echo "Il y a aussi $CONS mots ne contenant aucune voyelle.") |
sed -e "2,3s/^ *//
\$s/i */i /"
</pre>
</li>
<li><strong> <a name="shell11">
On veut chercher toutes les occurences des quatre <20>l<EFBFBD>ments (terre, air, eau,
feu) dans la premi<6D>re partie de <em>Germinal</em>. </a></strong>
<p>
On veut aussi que le r<>sultat soit plac<61> dans un fichier, et que le r<>sultat
soit class<73>&nbsp;: toutes les lignes qui contiennent <20>air<69>, puis toutes celles qui
contiennent <20>eau<61>, etc. </p>
<pre>
#!/bin/sh
FICHIER=resultat
MOTS="terre air eau feu"
[ -w $FICHIER ] &amp;&amp; echo "Le fichier $FICHIER existe d<>j<EFBFBD>" &amp;&amp; exit 1
for i in $MOTS;
do
echo "Lignes contenant $i" >> $FICHIER
grep $i zola*.txt >> $FICHIER
echo >> $FICHIER
done;
</pre>
</li>
<li><strong> <a name="shell12">
Chercher le mot <20>mine<6E> dans les chapitres 3, 4 et 5 de la premi<6D>re partie
de <em>Germinal</em>, et obtenir un fichier dans lequel figure le nombre
d'occurences du mot dans les fichiers, avec le num<75>ro des
lignes.</a></strong>
<pre>
#!/bin/sh
FICHIER=resultat
[ -w $FICHIER ] &amp;&amp; echo "Le fichier $FICHIER existe d<>j<EFBFBD>" &amp;&amp; exit 1
for i in zola[345].txt;
do
echo "Dans le fichier $i, voici les lignes contenant <20>mine<6E>" >> $FICHIER
NB=`grep -n mine $i | tee -a $FICHIER | wc -l`
(echo "$NB lignes";echo ) >> $FICHIER
done;
</pre>
</li>
<li><strong> <a name="shell13">
Cr<EFBFBD>ez un script <tt>coupe</tt> qui prend trois arguments, le premier <20>tant
un nom de fichier et les deux autres des entiers <em>l</em> et <em>l'</em>,
et qui affiche les lignes comprises entre <em>l</em> et <em>l'</em> dans le
fichier. Par exemple, </a></strong>
<pre>
coupe fic 4 8
</pre>
<p class="continue">
affichera les lignes 4 <20> 8 du fichier <tt>fic</tt>. Affichez des messages
en cas d'erreur (nombre de param<61>tres incorrect, fichier inexistant, etc).
</p>
<pre>
#!/bin/sh
[ $# != "3" ] &amp;&amp; echo "Nombre de param<61>tres incorrects" &amp;&amp; exit 1
[ ! -r $1 ] &amp;&amp; echo "Fichier $1 inexistant" &amp;&amp; exit 1
cat $1 | sed -n -e "$2,$3p"
</pre>
</li>
<li><strong> <a name="shell14">
Pour transformer une arborescence en un seul fichier compress<73>, on utilise
l'instruction</a></strong> <pre>tar zcvf nouveaunom fichiersaregrouper</pre>
<p>
Avant d'envoyer des fichiers <tt>tar</tt>, on utilise <tt>uuencode</tt>.
</p>
<p>
<strong><3E>crivez une commande <tt>tarmail</tt> qui prend deux arguments, une
adresse et un nom de r<>pertoire, et qui envoie par mail le contenu de
l'arborescence du r<>pertoire pr<70>c<EFBFBD>d<EFBFBD>e d'un message expliquant comment la
r<EFBFBD>cup<EFBFBD>rer.</strong></p>
<p><strong>
Note&nbsp;: pour r<>cup<75>rer un fichier uuencod<6F>, on tape <tt>uudecode</tt> et
pour reconstruire l'arborescence, on utilise <tt>tar zxvf fichier</tt>.
</strong></p>
<pre>
(echo "To: $1";
echo "Subject: $2";
echo " Pour lire ce document, sauvegardez ce mail (par exemple sous le "
echo "nom bidule) et faites ";
echo "uudecode bidule | tar tvzf -";
echo "pour r<>cup<75>rer les fichiers du r<>pertoire $2";
tar cvf - $2 | gzip | uuencode /dev/stdout) | mail $1
</pre>
</li>
<li><strong> <a name="shell15">
La commande suivante affiche le path complet de tous les fichiers finissant
par <tt>~</tt> (tilde) dans la sous-arborescence du r<>pertoire
courant.</a></strong>
<pre>
find . -name '*~'
</pre>
<p>
<EFBFBD>crivez un script qui prend en argument un nom de r<>pertoire et qui
d<EFBFBD>truit tous les fichiers&nbsp;:</p>
<ol>
<li>Finissant par <tt>~</tt>;</li>
<li>Commen<65>ant et finissant par un di<64>se;</li>
<li>S'appelant <tt>core</tt>;</li>
<li>S'appelant <tt>a.out</tt>.</li> </ol>
<pre>
#!/bin/sh
for i in `find . \( -name '*~' -o -name 'core' -o -name 'a.out' -o -name '#*#' \) -type f` ;
do
rm -f $i
done;
</pre>
</li>
<li><strong> <a name="shell16">
<EFBFBD>crire un script permettant d'appliquer divers filtres sur un fichier. Ce
script est lanc<6E> avec un argument, qui doit <20>tre un nom de fichier appel<65>
fichier de travail; dans le cas contraire, on affiche un message d'erreur.
On attend ensuite une commande en mode interactif, qui peut
<EFBFBD>tre&nbsp;:</a></strong>
<ul>
<li> <tt>end</tt>&nbsp;: le programme s'arr<72>te;</li>
<li> <tt>cherche</tt>&nbsp;: le programme lit alors une ligne au clavier
contenant un motif et une autre contenant un nom de fichier, puis <20>crit
dans ce fichier les lignes du fichier de travail contenant le motif;</li>
<li><tt>tete</tt> ou<tt>fin</tt>&nbsp;: le programme lit une ligne au clavier
contenant un entier <em>n</em> puis une ligne contenant un nom de fichier.
Il <20>crit ensuite les <em>n</em> premi<6D>res (resp. derni<6E>res) lignes du
fichier de travail dans le fichier pr<70>cis<69>;</li>
<li> autre chose&nbsp;: message d'erreur.</li>
</ul>
<pre>
#!/bin/sh
if [ $# != "1" ]; then echo "Indiquez un nom de fichier";exit 1; fi
if [ ! -r $1 ]; then echo "Fichier $1 inexistant";exit 1; fi
TRAVAIL=$1
while true;
do
read CMD
case $CMD in
end) exit 0;;
cherche) echo -n "Motif ? ";read MOTIF;
echo -n "Fichier ? ";read FICHIER;
if [ -w $FICHIER ]; then
echo "Le fichier $FICHIER existe d<>j<EFBFBD>";
else
grep $MOTIF $TRAVAIL &gt; $FICHIER
fi
;;
tete|fin)
echo -n "Lignes ? ";read LGN;
echo -n "Fichier ? ";read FICHIER;
if [ -w $FICHIER ]; then
echo "Le fichier $FICHIER existe d<>j<EFBFBD>";
else
case $CMD in
tete) head -n $LGN &lt; $TRAVAIL &gt; $FICHIER;;
fin) tail -n $LGN &lt; $TRAVAIL &gt; $FICHIER;;
esac
fi
;;
*) echo "Commande inexistante";;
esac
done
</pre>
</li>
</ol>
<div class="metainformation">
Auteur&nbsp;: Jo<4A>l Riou. Derni<6E>re modification le <date value="$Date: 2007-07-13 08:41:43 $"/>.
</div>
</body>
</html>