Pour certains exercices de TP (identifiés par l’étiquette VM), les manipulations demandent d’avoir des droits que nous n’avons pas sur le système d’exploitation réel de la machine, nous allons donc travailler dans une machine virtuelle (Ubuntu18.08), en tant que robert, dont le mot de passe est leffe.

On pourra envoyer des fichiers de la machine réelle à la machine virtuelle avec scp (ssh copy). Par exemple, dans un terminal sur la machine réelle,

scp Bureau/fichier robert@192.168.56.101:/home/robert/

Le premier argument est le chemin vers le fichier à transférer, le deuxième argument est le chemin de destination. Dans le deuxième chemin, avant le :, nous avons le login @ l’hôte (il s’agit de l’“autre” machine).

Sudo VM

  1. À quoi sert la commande sudo ?

  2. Tester les lignes de commandes suivantes :

    ls -al /root
    sudo ls -al /root
  3. Quels sont ses fichiers de configuration ? Que contiennent-ils ?

  4. Qui peut utiliser sudo ? Pourquoi robert peut-il faire sudo ?

XKCD 149

Utilisateurs et groupes VM

Les commandes adduser, addgroup et useradd permettent de créer des utilisateurs, des groupes sur le système.

  1. Parcourir les pages de manuel de ces commandes
  2. Tester les commandes useradd et adduser pour créer les utilisateurs roger et roland.
  3. Créer un utilisateur albert. Le rendre sudoer.
  4. Créer un groupe eleves.

Gestion de paquets VM

Debian et ses dérivés (ubuntu, mint, knoppix, grml, kali, damn small linux, xandros…) utilisent des paquets au format deb et les manipulent avec les commandes dpkg et apt. Il existe aussi des interfaces graphiques (par exemple synaptic) pour gérer l’installation et la suppression de logiciels.

De façon simplifiée, dpkg permet de manipuler les paquets eux-mêmes ; apt permet de rechercher des choses dans la base de données de paquets et de gérer les paquets (installation, désinstallation…) et leurs dépendances.

  1. Parcourir en diagonale les pages de manuel de ces 2 commandes.
  2. Mettre à jour la base de données des paquets.
  3. Quelle version de apparmor est installée ? Doit-elle être mise à jour ?
  4. Mettre à jour tous les paquets installés.
  5. Regarder le changelog de apparmor. Y a-t-il eu des mises à jour de sécurité récentes ?
  6. Quels paquets parlent de vache ?
  7. Installer cowsay. Quels fichiers ont été installés par ce paquet ?
  8. Installer zsh. Noter les paquets installés en plus (dépendances).
  9. Quel paquet a installé le fichier /bin/ls ?
  10. Quel paquet a installé le fichier /bin/sh ?
  11. Désinstaller zsh. Désinstaller ses dépendances.
  12. Combien de paquets sont actuellement installés ?
    1. Quels sont les paquets dont le nom contient beneath ?
    2. Énumérer les dépendances de ces paquets, y compris dépendances indirectes.
    3. Remarquer les numéros de versions ainsi que les incompatibilités (Breaks)
$ apt-get moo

                 (__) 
                 (oo) 
           /------\/ 
          / |    ||   
         *  /\---/\ 
            ~~   ~~   
..."Have you mooed today?"...

Scripts

Un script commence par un shebang, doit être exécutable (droits Unix), appelé avec son chemin s’il n’est pas dans le PATH du shell.

  1. Tester et interpréter le code suivant.

    #!/bin/sh
    
    FOO=Bonjour
    BAR=${FOO}Monde
    echo $BAR
    
    for i in *; do
    	echo $(realpath "$i")
    done
    
    if [ -d /tmp ]; then
    	if ls /tmp | grep 0; then
    		echo Oui
    	else
    	    touch /tmp/2024
    		echo Non
    	fi
    fi
  2. Dans un fichier truc.sh, recopier les lignes suivantes :

    #!/bin/sh
    
    echo "Bonjour"
    echo $0
    echo $1
    echo $2
    echo $#

    Rendre le fichier exécutable et le lancer. L’essayer avec des arguments divers.

    À quoi servent les variables $0, $1, $2 et $# ?

  3. Écrire un script shell qui liste les fichiers contenus dans un chemin donné en argument sans utiliser la commande ls. Les dossiers devront être listés avant les fichiers.

    Indice : on pourra broder sur la boucle for i in *; do echo "$i"; done. Dans cette boucle, * est un glob ; c’est un motif du shell pour capturer les noms de fichiers et dossiers.

Scripts pour utilisateurs et groupes VM

  1. Créer des utilisateurs pour chacun des élèves du fichier https://cygne.hainry.fr/cours/etudiants.tsv. Les utilisateurs auront pour login la première lettre de leur prénom suivi de leur nom (par exemple ehainry). Leur mot de passe sera leur login. Ils appartiendront au groupe eleves.

  2. Essayer avec la commande su de devenir l’un des utilisateurs créés. Vérifier avec whoami que le changement a bien eu lieu.

  3. Regarder les fichiers /etc/passwd et /etc/shadow pour vérifier que les utilisateurs ont bien été créés.

Variables d’environnement

La variable PATH contient les chemins dans lesquels le shell cherche les programmes à lancer.

  • Afficher le contenu de cette variable via la commande echo $PATH.
  • Modifier cette variable pour y ajouter le chemin de Desktop : PATH=$PATH:~/Bureau. Exécuter which firefox pour voir le chemin complet du navigateur. which ls.
  • Créer un script truc.sh dans ~/Bureau. Le lancer sans chemin. which truc.sh.
  • Modifier la variable PATH pour qu’elle ne contienne rien (PATH=). Qu’arrive-t-il aux commandes ?
  • La variable HOME contient le chemin de votre dossier personnel. La variable PWD contient le chemin courant. HOST contient le nom de l’ordinateur courant. RANDOM contient un nombre aléatoire (change à chaque appel). PROMPT contient l’invite de commande du shell.
  • la commande env permet de voir l’environnement.

Toutes ces variables se comportent comme PATH : si elles sont exportées, elles se transmettent aux processus fils ; le contenu de la variable est obtenu en le précédant d’un $.

Le fichier .bashrc est lu à chaque démarrage du shell. Si on veut que des réglages se conservent au prochain démarrage, on peut ajouter ces réglages dans ce fichier. Si on y met des commandes, elles seront elles aussi exécutées au démarrage du shell. Par exemple, ajoutons echo Bonjour $USER dans le .bashrc. Au prochain lancement de bash, nous serons salué.

  1. Changer la valeur de la variable HOME (par exemple pour /tmp). Que fait cd sans argument.
  2. Quelles autres variables sont données par env ?

Alias

Il est également possible d’ajouter des raccourcis de commande. Par exemple pour que cd.. fasse l’effet de cd .., on peut ajouter alias cd..="cd ..". On peut même aliaser des commandes existantes (par exemple remplacer ls par echo *, ou de façon plus intéressante lui ajouter des options).

  1. Créer un alias ll qui donnera la liste avec plus d’information que ls.
  2. Créer un alias acp qui donnera la version d’un paquet passé en argument.

FHS

Les systèmes Unix s’attachent à respecter un certain nombre de normes et standards, parmi ceux-ci, le FHS (Filesystem Hierarchy Standard) décrit la structure du système de fichier. Des distinctions existent dans certains Unix (en particulier Mac OSX), mais il est bon de connaître cette hiérarchie. Le tableau suivant est inspiré de Wikipedia.

Chemin Description
/bin Binaires (commandes) de base
/boot Amorçage (bootloader + noyaux)
/dev Périphériques (devices)
/etc Fichiers de configuration (Editable Text Configuration)
/home Répertoires utilisateurs
/lib Bibliothèques logicielles de base (libraries)
/media Points de montage pour les médias amovibles (clefs USB)
/mnt Points de montage temporaires (mount)
/proc Processus (système de fichiers virtuel)
/root Répertoire de l’utilisateur root
/sbin Binaires pour administrateur (system binaries)
/tmp Fichiers temporaires
/usr Hiérarchie système (contient des dossiers bin, lib, …)
/var Fichiers variables

Intéressons-nous maintenant plus en profondeur à certains de ces dossiers :

/dev

Les périphériques sont listés dans le dossier /dev. On peut ainsi y voir les disques durs /dev/[hs]d[a-e]\*. Des périphériques virtuels /dev/null, /dev/zero, /dev/random

  • Afficher le contenu de /dev/null.
  • Rediriger la sortie d’une commande vers /dev/null. Que contient /dev/null ?
  • À l’aide de la commande dd, copier 128 ko de /dev/zero dans un fichier.
  • Afficher le contenu du fichier (utiliser xxd ou hd plutôt que cat).
  • À l’aide de la commande dd, copier 128 ko de /dev/urandom dans un fichier. En afficher le contenu.

/proc

/proc
|-- 1
|   |-- cmdline
|   |-- environ
|   |-- fd
|   |   `-- ...
|   `-- status
|-- 1186
|   `...
|-- cpuinfo
|-- loadavg
|-- stat
|-- uptime
`-- version
  • man 5 proc
  • Trouver le PID de firefox et explorer le dossier de /proc correspondant. Regarder en particulier les fichiers et dossiers énumérés ci-dessus.
  • Trouver dans ce dossier le modèle du CPU, sa fréquence, son nombre de coeurs.
  • Trouver la version du noyau et de la distribution utilisée.
  • Trouver depuis combien de temps l’ordinateur tourne.

/etc

etc = Editable Text Configuration

Ce dossier abrite les fichiers de configuration générales au système des différents outils installés.

Nous avons déjà vu /etc/sudoers, /etc/passwd et /etc/shadow.

Mais on trouve aussi /etc/bash.bashrc : configuration de base du shell bash. /etc/apt/sources.list liste des dépôts utilisés par apt. /etc/hostname contient le nom de la machine…

Administration

Locate

Un service nommé updatedb se charge régulièrement d’indexer les fichiers présents sur la machine. Grace à lui, on peut localiser un fichier dont on connaît le nom mais pas le chemin.

  • locate firefox
  • man locate
  • man updatedb
  • man 5 mlocate.db

Tâches programmées

Il est possible de programmer des tâches pour qu’elles se lancent plus tard (par exemple dans 17 minutes ou à minuit) ou encore pour qu’elles soient exécutées régulièrement.

Autrefois, les commandes utilisées pour cela étaient cron, crontab et at. Aujourd’hui, sous Linux, c’est systemd qui s’en occupe ; sous macOS, c’est launchd qui s’en charge ; sous BSD, on utilise toujours cron et at.

Avec systemd, on utilise des timers. Les timers sont des fichiers décrivant les activités à faire et leur périodicité. Ils peuvent activer des services (qui sont eux-mêmes gérés par systemd)

  • systemctl list-timers
  • Choisir une UNIT, rechercher le fichier la décrivant, lire ce fichier.
  • Dans le fichier .timer, la ligne OnCalendar décrit quand ce service doit s’exécuter. Essayer de comprendre le codage de cette périodicité (man systemd.time).

On peut créer des tâches à n’exécuter qu’une seule fois. On parle alors de “Transient timers” (par opposition aux tâches répétées qui sont “persistent”).

  • Créer avec la commande systemd-run une tâche qui va copier le dossier Bureau dans un dossier backup dans quelques minutes.
  • Cette tâche apparait-elle dans la sortie de systemctl list-timers ?
  • Ces tâches sont effectuées dans un autre shell, donc la sortie de la commande n’apparaitra pas dans le terminal !

Arrêt et redémarrage VM

L’arrêt, le redémarrage et la veille d’une machine peuvent être exécutées depuis la ligne de commande. Cela se fera à l’aide de sous-commandes de systemctl (c’est-à-dire avec systemd).

  • systemctl poweroff

  • systemctl halt

  • systemctl reboot

  • systemctl hibernate

  • systemctl suspend

  • systemctl hybrid-sleep

  • Que font ces commandes ?

  • Qui a le droit d’exécuter ces commandes ?

Services

On nomme services (ou en Unix daemons) les programmes lancés en tâche de fond par le système. Par exemple le serveur ssh, le serveur http, le serveur postgresql sont des services. Il est possible de contrôler les services lancés : les stopper, les relancer, définir s’ils doivent être exécutés à chaque démarrage de l’ordinateur à l’aide de systemctl (encore une fois, sur les linux modernes, c’est systemd qui gère les services, sur d’autes systèmes, il peut s’agir d’upstart, init, sysV, launchd qui sont en général utilisables par la commande service).

Note : les commandes suivantes peuvent être “pipées” vers cat pour éviter dêtre en mode interactif.

  • systemctl status
  • systemctl list-units
  • systemctl list-unit-files

Les unit sont donc des fichiers définissant la façon de lancer un service et les units dont il dépend. Ainsi le sshd.service nécessite d’avoir du réseau (network.target) et est nécessaire pour le démarrage en mode multi-utilisateur (multi-user.target). Note : les target sont des unités qui ne lancent pas forcément de programmes mais sont pratiques pour définir les dépendances.

  • Trouver les informations de dépendances de sshd.

Certains services ne sont pas lancés au démarrage mais quand ils sont utilisés. Ainsi, pour un serveur http ou ssh ou…, on pourrait décider de ne lancer le serveur que si une connexion sur le port 80 (respectivement 22) est demandée. Dans ce cas, on a des unit qui sont des .socket au lieu de .service. Cela signifie que les informations transmises par netstat ou ss sur les ports sur lesquels l’ordinateur écoute peuvent ne pas être tout à fait fiable : le fait que systemd écoute sur le port 80 pour savoir s’il faut lancer un serveur http n’implique pas que le serveur fonctionne.

Scripts (2)

  1. Écrire un script myps.sh qui liste les processus lancés (PID, commande, propriétaire) sans utiliser la commande ps.

    Indice : on peut utiliser /proc.

  2. Écrire un script pause.sh chargé de mettre en pause un processus donné par son nom. L’usage de ce script sera ./pause.sh firefox par exemple. Dans cet exemple, le script enverra le signal STOP au processus firefox, patientera 10 secondes puis enverra le signal CONT à ce même processus. (Note : l’utilisation de ps est autorisée)

    1. Écrire un script shell de backup. Il prendra en argument le dossier à sauvegarder. Il archivera, compressera et chiffrera ce dossier. Puis il enverra l’archive chiffrée sur un serveur connu. Une fois l’archive envoyée sans erreur, il supprimera les fichiers intermédiaires, et sur le serveur ne conservera que les 3 backups les plus récents.

      On utilisera tar pour l’archivage/compression ; openssl bf pour le chiffrement ; le nom de l’archive chiffrée devra contenir la date et l’heure du backup.

    2. Écrire un script de rollback qui récupèrera le backup le plus récent et le décompressera dans un dossier donné en argument au script.

    3. Planifier une sauvegarde tous les jours à 13h.

  3. Écrire un script shell qui explore /var/log en cherchant dans tous les fichiers non gzippés les IPs qui apparaissent. Énumérer ces IPs et les fichiers où elles apparaissent.

  4. Écrire un script créant un fichier html joli présentant les informations sur le système :

    • le nom de l’ordinateur,
    • son IP
    • la distribution linux utilisée
    • l’espace disque
    • la mémoire présente et disponible
    • la configuration réseau
    • le processeur
    • les partitions
  5. Écrire un script qui va lire un fichier de balisage léger (inspiré de txt2tags) et produire un fichier html correspondant. Par exemple, le fichier suivant :

    = Titre 1 =
    == Sous-titre ==
    Un paragraphe sur une ligne.
    Un deuxième paragraphe qui contient **du texte en gras** et du //texte en italique//.
    == Deux ==

    deviendra un fichier html dont le body ressemblera à

    <h1>Titre 1</h1>
    <h2>Sous-titre</h2>
    <p>Un paragraphe sur une ligne.</p>
    <p>Un deuxième paragraphe qui contient <b>du texte en gras</b> et du <i>texte en italique</i>.</p>
    <h2>Deux</h2>
  6. Écrire un script invtree qui lit sur l’entrée standard une arborescence (telle qu’elle pourrait être donnée par la commande tree -m) et crée les dossiers pour reproduire cette arborescence.

    Tester avec l’arborescence suivante :

     .
     |-- m1105
     |   |-- colle_amphi
     |   |-- colles_tp
     |   |-- docs
     |   `-- tps
     |-- m1207
     |   |-- colles
     |   |   `-- colletp
     |   |-- poly
     |   |   `-- progs
     |   `-- python
     |-- m2105
     |   |-- colles
     |   |-- tp1
     |   |-- tp2
     |   |-- tp3
     |   `-- tp4
     |-- m3206
     `-- m4208c