Solutions des exercices sur le système

Les droits

  1. Changez les droits d'un fichier fic1 pour que tous ceux de votre groupe puissent écrire dedans.
    chmod g+w fic1
    
  2. Donnez en une seule ligne le droit d'exécution à tous les utilisateurs d'un fichier script qui n'a jusqu'alors que des droits standards (-rw-r--r--).
    chmod uog+x script
    
  3. Le fichier toto a les droits suivants : -rwxr--r--. Modifiez-en les droits en une ligne de commande de sorte que le propriétaire n'ait plus que le droit de lecture.
    chmod u-wx toto
    
  4. Modifier les droits du fichier toto (-rwxr--r--) de sorte que le groupe et les autres utilisateurs aient les mêmes droits que le propriétaire.
    chmod og+wx toto
    
  5. Quelle option permet de modifier récursivement les droits d'un répertoire et des fichiers qu'il contient ?

    C'est l'option -R. Par exemple, pour interdire tous les droits aux fichiers présents dans une branche du répertoire confidentiel, on peut faire :

    chmod -R og-rwx confidentiel
    
  6. Quelle option de mkdir permet de créer un répertoire en spécifiant les droits sur ce répertoire ?

    C'est l'option -m qui permet de le faire. Par exemple, pour créer un répertoire en lecture interdite aux autres :

    mkdir -m og-r repertoire
    
  7. Affichez et interprétez les droits de /usr/sbin/mount.
    bireme ~ $ ll /usr/sbin/mount 
    -r-xr-xr-x   1 root     bin         27208 Jan  9  2000 /usr/sbin/mount*
    
    Il s'agit d'un fichier éxécutable par tout utilisateur.

Les liens

  1. Vous avez chez vous un répertoire tmp/ qui contient un fichier bidon. Créez un lien physique sur tmp/bidon appelé blo, dans votre répertoire d'accueil (HOME). Comparez les contenus de tmp/bidon et de blo. Que contient blo ?
    ln tmp/bidon blo
    
    Les contenus sont identiques. Les noms de fichiers tmp/bidon et blo renvoient au même endroit sur le disque dur.
  2. Même question avec un lien symbolique.
    ln -s tmp/bidon blo
    
    Le contenu semble être identique, cependant, à propos du blo, le disque dur ne contient comme information que le nom du fichier vers lequel le lien pointe (tmp/bidon).
  3. Quelles sont les différences entre les liens durs et les liens symboliques ?

    On vient d'en voir une. On en déduit que le temps d'accès au contenu d'un lien dur est plus rapide que pour un lien symbolique. Une autre différence notable est que, contrairement aux liens symboliques, un lien dur ne peut pas pointer vers un répertoire.

  4. Dans quel cas ne peut-on pas faire de lien physique ? Que faut-il faire ?

    On ne peut pas faire de lien dur vers un répertoire. Dans ce cas, il faut donc utiliser un lien symbolique.

  5. Quel est l'effet de chmod sur un lien ?

    S'il s'agit d'un lien dur, les droits des deux fichiers liés sont modifiés. En revanche, s'il s'agit d'un lien symbolique, les deux fichiers peuvent avoir des droits différents.

Les processus

  1. Affichez la liste des processus associés à votre terminal. Affichez la liste des processus dont vous êtes propriétaire. Recommencez en utilisant l'option -l. À quoi correspondent les colonnes PID et PPID ?
    bireme ~ $ 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
    bireme ~ $ 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
    

    Les numéros apparaissant dans la colonne PID sont les numéros des différents processus. Le PPID désigne lui le numéro du processus père du processus en question. Par exemple, ici, le processus 16992 (vim) est un fils du processus 16970 (zsh).

  2. Lancez une commande longue en arrière plan. Quel est le comportement du processus associé lorsqu'il reçoit les signaux suivants :

    Pour envoyer un signal à un processus, on peut faire :

    bireme ~ $ kill -23 17382
    

    17382 désignant un numéro de processus (PID) et 23 le numéro d'un signal (SIGSTOP).

  3. Utilisez la commande nice pour lancer des commandes ayant une faible priorité.
    bireme ~ $ nice -19 ./calcul
    
  4. Interprétez la hiérarchie des processus qui vous appartiennent.

    Pour vous aider à comprendre, vous pouvez afficher un arbre en lançant la commande pstree (FreeBSD) ou ptree (Solaris).

  5. La commande ps | wc compte deux processus en plus de ceux qui existent réellement lorsqu'on lance la commande. Pourquoi ?

    Ce sont les processus associés aux commandes ps et wc que vous venez de lancer !

  6. Donner deux commandes pour reprendre l'exécution d'une instruction interrompue par un ^Z.

    Vous disposez des commandes fg et bg. fg permet de poursuivre le déroulement du programme. bg le fait aussi mais il relance le programme en tâche de fond.

Programmation du shell

  1. Faites deux scripts qui vous disent bonjour en affichant votre login («Bonjour, toto») :

    Il faut éditer un fichier saluer et le rendre ensuite éxécutable :

    #!/bin/sh
    if [ -n "$1" ]; then LOGIN=$1; else LOGIN=`whoami`; fi
    echo "Bonjour, $LOGIN"
    
  2. Faire un script qui affiche la phrase : Le script [params] a [n] paramètre(s), que voici : [paramètres], en remplaçant les mots entre crochets par leur valeur; par exemple :
    chaland ~ $ params bla ble bli blo blu  
    La commande params a 5 paramètre(s), que voici : bla ble bli blo blu
    
    #!/bin/sh
    echo "La commande $0 a $# paramètre(s), que voici| : $@"
    
  3. Créez une commande qui, lorsqu'elle est appelée, renvoie le nombre d'arguments qui lui ont été fournis, ainsi que le premier de ces arguments.
    #!/bin/sh
    echo "J'ai reçu $# arguments"
    echo "Le premier d'iceux est $1"
    
  4. Vous voulez écrire un script qui vous dit combien de personnes sont loguées sur une machine donnée; par exemple :
    drakkar ~ $ combien galion
    Il y a 5 personne(s) loguées sur galion en ce moment.
    drakkar ~ $
    
    #!/bin/sh
    N=`who | wc -l | sed -e "s/ *//"`
    MACHINE=`whoami`
    echo "Il y a $N personne(s) logués sur $MACHINE en ce moment"
    
  5. On veut remplacer le suffixe .htm d'un ensemble de fichiers en .html.

    Le script suivant lancé avec "**/*.htm" comme paramètre devrait fonctionner :

    #!/bin/sh
    for i in $@;
    do
    mv $i `echo $i | sed -e "s/htm$/html/"`
    done;
    
  6. Un ensemble de noms de fichiers sont en majuscules. On veut tout basculer en minuscules.
    #!/bin/sh
    for i in $@;
    do
    mv $i `echo $i | tr '[:upper:]' '[:lower:]'`
    done;
    
  7. Créez un script indice qui affiche l'indice de son premier argument dans la liste des arguments suivants. Par exemple,
    indice toto tata titi toto tutu
    

    renvoie l'indice de toto dans la liste tata titi toto tutu, c'est-à-dire 3.

    #!/bin/sh
    ARG=$1
    shift
    N=0
    
    for i in $@;
    do
    N=`expr $N + 1`
    [ x$ARG = x$i ] && echo $N
    done;
    
  8. On ne s'intéresse ici qu'à des fichiers contenant un mot par ligne. Écrire un script qui compte le nombre de mots contenant une des lettres «r», «s» ou «t», 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 :
    Dans ce fichier,  vous avez :
    45 mots contenant «r», «s» ou «t», et parmi eux, 
    12 contiennent deux de ces lettres au moins.
    Il y a aussi 10 mots ne contenant aucune voyelle.
    
    #!/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 «r», «s» ou «t» 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 /"
    
  9. On veut chercher toutes les occurences des quatre éléments (terre, air, eau, feu) dans la première partie de Germinal.

    On veut aussi que le résultat soit placé dans un fichier, et que le résultat soit classé : toutes les lignes qui contiennent «air», puis toutes celles qui contiennent «eau», etc.

    #!/bin/sh
    
    FICHIER=resultat
    MOTS="terre air eau feu"
    
    [ -w $FICHIER ] && echo "Le fichier $FICHIER existe déjà" && exit 1
    
    for i in $MOTS;
    do
    echo "Lignes contenant $i" >> $FICHIER
    grep $i zola*.txt >> $FICHIER
    echo >> $FICHIER 
    done;
    
    
  10. Chercher le mot «mine» dans les chapitres 3, 4 et 5 de la première partie de Germinal, et obtenir un fichier dans lequel figure le nombre d'occurences du mot dans les fichiers, avec le numéro des lignes.
    #!/bin/sh
    
    FICHIER=resultat
    
    [ -w $FICHIER ] && echo "Le fichier $FICHIER existe déjà" && exit 1
    
    for i in zola[345].txt; 
    do
    echo "Dans le fichier $i, voici les lignes contenant «mine»" >> $FICHIER
    NB=`grep -n mine $i | tee -a $FICHIER | wc -l` 
    (echo "$NB lignes";echo ) >> $FICHIER
    done;
    
  11. Créez un script coupe qui prend trois arguments, le premier étant un nom de fichier et les deux autres des entiers l et l', et qui affiche les lignes comprises entre l et l' dans le fichier. Par exemple,
    coupe fic 4 8
    

    affichera les lignes 4 à 8 du fichier fic. Affichez des messages en cas d'erreur (nombre de paramètres incorrect, fichier inexistant, etc).

    #!/bin/sh
    
    [ $# != "3" ] && echo "Nombre de paramètres incorrects" && exit 1
    [ ! -r $1 ] && echo "Fichier $1 inexistant" && exit 1
    
    cat $1 | sed -n -e "$2,$3p"
    
    
  12. Pour transformer une arborescence en un seul fichier compressé, on utilise l'instruction
    tar zcvf nouveaunom fichiersaregrouper

    Avant d'envoyer des fichiers tar, on utilise uuencode.

    Écrivez une commande tarmail 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écédée d'un message expliquant comment la récupérer.

    Note : pour récupérer un fichier uuencodé, on tape uudecode et pour reconstruire l'arborescence, on utilise tar zxvf fichier.

    (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érer les fichiers du répertoire $2";
    tar cvf - $2 | gzip | uuencode /dev/stdout) | mail $1
    
  13. La commande suivante affiche le path complet de tous les fichiers finissant par ~ (tilde) dans la sous-arborescence du répertoire courant.
    find . -name '*~'
    

    Écrivez un script qui prend en argument un nom de répertoire et qui détruit tous les fichiers :

    1. Finissant par ~;
    2. Commençant et finissant par un dièse;
    3. S'appelant core;
    4. S'appelant a.out.
    #!/bin/sh
    
    for i in `find . \( -name '*~' -o -name 'core' -o -name 'a.out' -o -name '#*#' \) -type f` ;
    do
    rm -f $i
    done;
    
    
  14. Écrire un script permettant d'appliquer divers filtres sur un fichier. Ce script est lancé avec un argument, qui doit être un nom de fichier appelé fichier de travail; dans le cas contraire, on affiche un message d'erreur. On attend ensuite une commande en mode interactif, qui peut être :
    #!/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à";
             else
                grep $MOTIF $TRAVAIL > $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à";
             else
                case $CMD in
                tete) head -n $LGN < $TRAVAIL > $FICHIER;;
                fin)  tail -n $LGN < $TRAVAIL > $FICHIER;;
                esac
             fi
             ;;
    
    *)       echo "Commande inexistante";;
    esac
    done
    
    
Auteur : Joël Riou. Dernière modification le 2002-12-10.