Aller au contenu
L'arborescence et les chemins

L'arborescence et les chemins

100 Comprendre ⏱ 1 h linuxbashubuntudebian

À la fin, vous saurez

  • Expliquer le rôle des principaux répertoires d'un système Linux selon la FHS
  • Se déplacer avec cd et pwd en chemins absolus et relatifs, avec ~, . , .. et cd -
  • Lire chaque colonne de ls -l et choisir les options de ls adaptées
  • Reconnaître le type d'un fichier avec ls -l, file et stat
  • Utiliser les motifs *, ? et [ ] et prévoir leur expansion, en les distinguant des accolades
  • Décider où ranger le programme, la configuration, les données et les journaux d'une application

Prérequis

Testé avec bash 5.2.21 coreutils 9.4 ubuntu 24.04 util-linux 2.39.3 , vérifié le 5 octobre 2026

Pourquoi

On vous demande trois choses sur sig-app-1 : retrouver le fichier de configuration de Signalements pour vérifier l'adresse de la base de données, regarder la taille de ses journaux, et dire où sont stockées les photos jointes aux signalements. Sous Windows, vous auriez cherché dans C:\Program Files. Ici, il n'y a pas de lettre de lecteur, pas de dossier « Programmes », et ls dans votre répertoire personnel ne montre rien d'intéressant.

Linux range tout dans une seule arborescence, selon des conventions vieilles de trente ans et étonnamment stables. Ceux qui les connaissent trouvent la configuration d'un service qu'ils n'ont jamais vu en quelques secondes : elle est dans /etc. Ceux qui ne les connaissent pas cherchent partout, et rangent leurs propres applications n'importe où, ce qui complique les sauvegardes, les mises à jour et la sécurité. Cette leçon donne la carte, apprend à s'y déplacer, et montre comment lire ce que ls affiche, colonne par colonne.

Les concepts

Une seule racine

Tout fichier, sur un système Linux, a une place dans un arbre unique dont la racine s'écrit /. Les disques, les partitions, les clés USB, les partages réseau ne sont pas des lecteurs séparés : ils sont montés à un endroit de l'arbre, et leur contenu apparaît sous ce répertoire. Un second disque monté sur /srv fait apparaître son contenu dans /srv, sans que les programmes aient à le savoir.

Le caractère / sert aussi de séparateur dans les chemins : /var/log/syslog désigne le fichier syslog, dans le répertoire log, dans le répertoire var, à la racine. Les noms sont sensibles à la casse : Signalements, signalements et SIGNALEMENTS sont trois fichiers différents. Un nom peut contenir presque tous les caractères, espaces compris, sauf / et le caractère nul ; c'est une source de pièges (leçon 2 et plus bas).

La FHS : une place pour chaque chose

La FHS (Filesystem Hierarchy Standard), maintenue par la Linux Foundation (version 3.0, 2015), décrit ce que contient chaque répertoire. Les distributions la suivent dans les grandes lignes, avec quelques écarts documentés (les pages hier(7) et, pour les systèmes qui utilisent systemd, file-hierarchy(7), décrivent la pratique actuelle). Les répertoires qu'il faut connaître sur un serveur :

RépertoireCe qu'il contientSur sig-app-1
/etcLa configuration propre à la machine, en fichiers texte/etc/ssh/sshd_config, /etc/signalements/
/usrLes programmes, bibliothèques et données installés par la distribution, en lecture seule en fonctionnement normal/usr/bin/ls, /usr/lib/, /usr/share/doc/
/usr/localLa même chose pour ce que l'administrateur installe à la main, hors paquetsUn outil compilé localement
/optLes logiciels additionnels livrés en un bloc, un sous-répertoire par logiciel/opt/signalements/
/varLes données variables : ce qui change pendant le fonctionnement
/var/logLes journaux/var/log/syslog, /var/log/auth.log, /var/log/journal/
/var/libL'état persistant des programmes/var/lib/postgresql/, /var/lib/docker/
/var/cache, /var/tmpCaches reconstructibles ; fichiers temporaires qui survivent au redémarrage
/srvLes données servies par la machine (sites, fichiers)
/homeLes répertoires personnels des utilisateurs/home/camille
/rootLe répertoire personnel de root, hors de /home
/tmpLes fichiers temporaires, effacés au redémarrage ou périodiquement
/runLes données d'exécution (numéros de processus, sockets), en mémoire, vidées à chaque démarrage/run/systemd/journal/socket
/bootLe noyau et les fichiers du chargeur d'amorçage/boot/vmlinuz-...
/devLes fichiers de périphériques/dev/null, /dev/sda
/proc, /sysDes systèmes de fichiers virtuels fabriqués par le noyau/proc/version (leçon 1)
/mnt, /mediaPoints de montage temporaires, et des supports amovibles

La FHS range ces répertoires selon deux critères qui en expliquent la logique. Un fichier est statique (programmes, bibliothèques, documentation : il ne change pas sans intervention de l'administrateur) ou variable ; il est partageable entre plusieurs machines ou propre à une seule. /usr est statique et partageable : on pourrait le monter en lecture seule. /etc est statique mais propre à la machine. /var est variable. C'est ce découpage qui rend possibles des choix d'exploitation simples : sauvegarder /etc et /var/lib, pas /usr, qu'une réinstallation des paquets reconstitue ; mettre /var sur un disque séparé pour qu'un journal qui enfle ne remplisse pas tout le système.

La fusion de /usr

Historiquement, /bin, /sbin et /lib contenaient les programmes indispensables au démarrage, et /usr/bin, /usr/sbin, /usr/lib le reste, parce que /usr pouvait se trouver sur un autre disque monté plus tard. Cette distinction n'a plus de raison d'être, et les distributions ont fusionné les deux : sur Debian depuis la version 12 (bookworm), sur Ubuntu, Fedora et RHEL, /bin n'est plus qu'un lien symbolique vers /usr/bin :

$ ls -ld /bin /sbin /lib /lib64
lrwxrwxrwx 1 root root 7 Apr 22  2024 /bin -> usr/bin
lrwxrwxrwx 1 root root 7 Apr 22  2024 /lib -> usr/lib
lrwxrwxrwx 1 root root 9 Apr 22  2024 /lib64 -> usr/lib64
lrwxrwxrwx 1 root root 8 Apr 22  2024 /sbin -> usr/sbin

Conséquence pratique : /bin/ls et /usr/bin/ls sont le même fichier, d'où le doublon dans type -a echo à la leçon 2. Les chemins anciens continuent de fonctionner.

Répertoire personnel, répertoire courant

Chaque utilisateur a un répertoire personnel (home directory), /home/camille pour vous. C'est là que vous arrivez à la connexion, et là que vont vos fichiers et votre configuration personnelle. Le shell l'abrège en ~ (tilde) ; ~paul désigne celui de l'utilisateur paul.

Chaque processus a un répertoire courant (working directory) : le point de l'arbre à partir duquel il interprète les chemins relatifs. Pour le shell, c'est l'endroit « où vous êtes ». pwd (print working directory) l'affiche, cd (change directory) le change.

Chemins absolus et relatifs

Un chemin désigne un fichier dans l'arbre. Il en existe deux sortes :

  • un chemin absolu commence par / : il part de la racine, et désigne le même fichier où que vous soyez (/etc/signalements/env) ;
  • un chemin relatif ne commence pas par / : il part du répertoire courant (journaux/acces.log, ../config).

Deux noms spéciaux existent dans chaque répertoire : . désigne le répertoire lui-même, .. son parent. ../.. remonte de deux niveaux ; ./script.sh désigne script.sh dans le répertoire courant (forme obligatoire pour lancer un programme qui n'est pas dans PATH, leçon 7). Le parent de / est / lui-même.

Quand utiliser lequel ? En exploration, les relatifs vont plus vite. Dans un script, une unité systemd, une tâche planifiée, une documentation : toujours des chemins absolus, parce que le répertoire courant d'un programme lancé automatiquement n'est pas celui que vous imaginez.

Les fichiers cachés

Un fichier dont le nom commence par un point (.bashrc, .ssh) est caché : ls ne l'affiche pas sans -a, et le motif * ne le désigne pas. Ce n'est pas une protection, juste une convention pour ranger la configuration des utilisateurs sans encombrer leur répertoire. Votre répertoire personnel en contient plusieurs : .bashrc (configuration du shell, leçon 7), .bash_history (leçon 2), .ssh/ (vos clés et la liste des serveurs connus).

Les types de fichiers

« Tout est fichier » est une formule célèbre d'Unix, et presque vraie : l'arbre contient, en plus des fichiers ordinaires et des répertoires, des objets de natures différentes, que ls -l distingue par le premier caractère de chaque ligne :

CaractèreTypeExemple
-Fichier ordinaire/etc/os-release (sa cible, plus exactement)
dRépertoire/etc
lLien symbolique, qui pointe vers un autre chemin/bin -> usr/bin
cPériphérique en mode caractère (flux d'octets)/dev/null, /dev/urandom
bPériphérique en mode bloc (disque)/dev/sda, /dev/nvme0n1
sSocket : point de communication entre processus/run/systemd/journal/socket
pTube nommé (FIFO)Rare sur un serveur

Ces objets s'ouvrent, se lisent et s'écrivent avec les mêmes appels système que des fichiers (leçon 1). Écrire dans /dev/null ne fait rien (on s'en sert pour jeter une sortie, leçon 6) ; lire /dev/urandom donne des octets aléatoires ; lire /proc/loadavg donne la charge de la machine, calculée par le noyau au moment de la lecture.

Les motifs du shell

Le shell sait remplacer un motif par la liste des fichiers qui y correspondent, avant même de lancer la commande (expansion des chemins, leçon 2). Trois caractères spéciaux :

  • * correspond à n'importe quelle suite de caractères, y compris vide : *.log ;
  • ? correspond à exactement un caractère : acces-2026-10-0?.log ;
  • [...] correspond à un caractère parmi ceux listés : [12] (1 ou 2), [0-9] (un chiffre), [!0-9] (tout sauf un chiffre).

Par défaut, * et ? ne correspondent pas au point initial d'un fichier caché, et un motif qui ne correspond à rien est laissé tel quel. Ces motifs sont appelés globs (le nom vient d'un ancien programme d'Unix, glob, qui faisait ce travail avant d'être intégré au shell).

Les accolades se ressemblent, mais ne sont pas des motifs : {recette,production}.env est remplacé par recette.env production.env que ces fichiers existent ou non. C'est une génération de texte, pas une recherche. Elle sert à écrire vite : cp signalements.conf{,.orig} devient cp signalements.conf signalements.conf.orig.

En pratique

Les sorties ont été produites sur une Ubuntu 24.04, avec LC_ALL=C.UTF-8, dans un répertoire d'essai ; le nom de l'utilisateur a été remplacé par camille.

Se situer et se déplacer

$ pwd
/home/camille
$ cd /var/log
$ pwd
/var/log
$ cd ..
$ pwd
/var
$ cd -
/var/log
$ cd
$ pwd
/home/camille
  • cd /var/log : chemin absolu.
  • cd .. : remonter au parent.
  • cd - revient au répertoire précédent et l'affiche ; deux cd - successifs font l'aller-retour entre deux répertoires, très pratique entre la configuration et les journaux d'un service.
  • cd sans argument ramène au répertoire personnel, comme cd ~.

pwd affiche le chemin par lequel vous êtes arrivé, liens symboliques compris. pwd -P affiche le chemin physique, liens résolus : après cd /bin, pwd affiche /bin, pwd -P affiche /usr/bin.

Faire le tour de la racine

$ ls /
bin                lib.usr-is-merged  proc                srv
bin.usr-is-merged  lib64              root                swap.img
boot               lost+found         run                 sys
cdrom              media              sbin                tmp
dev                mnt                sbin.usr-is-merged  usr
etc                opt                snap                var
home

Vous retrouvez les répertoires du tableau, et quelques intrus. Sur Ubuntu 24.04, les répertoires *.usr-is-merged sont des marqueurs laissés par la transition vers la fusion de /usr. lost+found sert à l'outil de réparation du système de fichiers ext4. snap est le répertoire des paquets Snap de Canonical. cdrom et swap.img (un fichier d'échange) dépendent de la façon dont la machine a été installée : cette sortie vient d'un poste de travail, et un serveur installé depuis une image de cloud n'en a pas forcément.

Lire ls -l, colonne par colonne

Dans un répertoire d'essai qui imite les journaux d'accès de Signalements :

$ ls -l journaux
total 2448
-rw-rw-r-- 1 camille camille       0 Oct  1 08:00 acces-2026-10-01.log
-rw-rw-r-- 1 camille camille       0 Oct  2 08:00 acces-2026-10-02.log
-rw-rw-r-- 1 camille camille 2500000 Oct  3 23:59 acces-2026-10-03.log
-rw-rw-r-- 1 camille camille       7 Oct  3 14:12 erreurs-2026-10-03.log
  • total 2448 : l'espace disque occupé par les fichiers listés, en blocs de 1 Kio. Il peut différer de la somme des tailles (un fichier occupe des blocs entiers, et un fichier « creux » peut annoncer une taille supérieure à ce qu'il occupe).
  • -rw-rw-r-- : le type (premier caractère, ici - pour un fichier ordinaire), puis les permissions, trois groupes de trois caractères pour le propriétaire, le groupe et les autres. La leçon 9 les détaille.
  • 1 : le nombre de liens physiques vers ce fichier (leçon 4). Pour un répertoire, ce nombre compte ses sous-répertoires plus deux (. et l'entrée dans son parent).
  • camille camille : le propriétaire, puis le groupe (leçon 8).
  • 2500000 : la taille en octets.
  • Oct 3 23:59 : la date de dernière modification du contenu. Pour un fichier modifié il y a plus de six mois, ls affiche l'année au lieu de l'heure.
  • acces-2026-10-03.log : le nom.

Les options qui servent tous les jours :

$ ls -lh journaux
total 2.4M
-rw-rw-r-- 1 camille camille    0 Oct  1 08:00 acces-2026-10-01.log
-rw-rw-r-- 1 camille camille    0 Oct  2 08:00 acces-2026-10-02.log
-rw-rw-r-- 1 camille camille 2.4M Oct  3 23:59 acces-2026-10-03.log
-rw-rw-r-- 1 camille camille    7 Oct  3 14:12 erreurs-2026-10-03.log
$ ls -lt journaux
total 2448
-rw-rw-r-- 1 camille camille 2500000 Oct  3 23:59 acces-2026-10-03.log
-rw-rw-r-- 1 camille camille       7 Oct  3 14:12 erreurs-2026-10-03.log
-rw-rw-r-- 1 camille camille       0 Oct  2 08:00 acces-2026-10-02.log
-rw-rw-r-- 1 camille camille       0 Oct  1 08:00 acces-2026-10-01.log
  • -h (human-readable) : tailles en Kio, Mio, Gio. 2.4M pour 2 500 000 octets, parce que ls compte en puissances de 1 024 (2 500 000 / 1 048 576 ≈ 2,38). --si utilise les puissances de 1 000.
  • -t : tri par date de modification, le plus récent en premier. ls -ltr inverse l'ordre (-r), et met le plus récent en bas, juste au-dessus de l'invite : c'est la forme habituelle pour trouver le dernier journal écrit.
  • -a : affiche aussi les fichiers cachés, et . et ... -A les affiche sans . ni ...
  • -d : affiche le répertoire lui-même au lieu de son contenu. ls -l /etc liste les fichiers de /etc ; ls -ld /etc affiche une ligne sur /etc, pour voir ses permissions.
  • -R : parcourt récursivement les sous-répertoires. Utile sur un petit arbre ; sur un gros, préférez find (leçon 4).
  • -i : affiche le numéro d'inode (voir Sous le capot).

Les fichiers cachés

$ ls -la
total 16
drwxrwxr-x 3 camille camille 4096 Oct  5 11:10 .
drwxrwxr-x 6 camille camille 4096 Oct  5 11:09 ..
-rw-rw-r-- 1 camille camille    0 Oct  5 11:10 .cache
drwxrwxr-x 2 camille camille 4096 Oct  5 11:10 journaux
lrwxrwxrwx 1 camille camille    8 Oct  5 11:10 lien -> note.txt
-rw-rw-r-- 1 camille camille    8 Oct  5 11:09 note.txt

Le fichier .cache n'apparaissait pas sans -a. On voit aussi un lien symbolique (l en tête, et lien -> note.txt qui indique sa cible) et deux répertoires (d), dont la taille affichée, 4 096 octets, est celle de la table des noms qu'ils contiennent, pas celle de leur contenu. Pour la taille réelle d'un répertoire et de tout ce qu'il contient, c'est du -sh journaux.

Identifier un fichier

ls -l donne le type selon le noyau. file regarde le contenu pour dire de quoi il s'agit :

$ file /usr/bin/ls /etc/os-release /usr/bin/which /dev/null
/usr/bin/ls:     ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=44900829b39271d878615772bb2a6ffa422f0891, for GNU/Linux 3.2.0, stripped
/etc/os-release: symbolic link to ../usr/lib/os-release
/usr/bin/which:  symbolic link to /etc/alternatives/which
/dev/null:       character special (1/3)

/usr/bin/ls est un programme compilé au format ELF, pour processeurs x86-64, qui utilise des bibliothèques partagées chargées par /lib64/ld-linux-x86-64.so.2 (le chargeur de la glibc, celui qui manque sur Alpine, leçon 1). file ne se fie pas à l'extension : sous Linux, .txt ou .log ne sont que des conventions de nommage, et un fichier sans extension peut être n'importe quoi. C'est pourquoi file est le premier réflexe devant un fichier inconnu, avant de l'ouvrir ou de l'exécuter.

stat donne toutes les métadonnées d'un fichier :

$ stat note.txt
  File: note.txt
  Size: 8         	Blocks: 8          IO Block: 4096   regular file
Device: 259,2	Inode: 25456002    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/ camille)   Gid: ( 1000/ camille)
Access: 2026-10-05 11:09:40.006067336 +0200
Modify: 2026-10-05 11:09:39.990043423 +0200
Change: 2026-10-05 11:09:39.990043423 +0200
 Birth: 2026-10-05 11:09:39.989067384 +0200

On y lit la taille (8 octets) et l'espace occupé (8 blocs de 512 octets, soit un bloc de 4 Kio du système de fichiers), le numéro d'inode, le nombre de liens, les permissions en octal et en lettres (leçon 9), les numéros d'utilisateur et de groupe, et quatre dates : dernier accès (Access), dernière modification du contenu (Modify, celle de ls -l), dernier changement des métadonnées (Change : permissions, propriétaire, nom), et création (Birth, quand le système de fichiers la conserve, ce qui est le cas d'ext4).

Les motifs

$ ls journaux/acces-*
journaux/acces-2026-10-01.log
journaux/acces-2026-10-02.log
journaux/acces-2026-10-03.log
$ ls journaux/*-2026-10-0[12].log
journaux/acces-2026-10-01.log
journaux/acces-2026-10-02.log
$ echo journaux/*.txt
journaux/*.txt
$ echo {recette,production}.env
recette.env production.env

La troisième commande montre la règle par défaut de Bash : aucun fichier ne correspond à *.txt, donc le motif est passé tel quel à echo. Avec ls, vous auriez obtenu une erreur No such file or directory pour un fichier nommé littéralement *.txt. La quatrième montre que les accolades génèrent du texte sans rien vérifier : aucun de ces fichiers n'existe.

Pour voir ce que le shell va réellement passer à une commande, remplacez la commande par echo : echo rm journaux/acces-* affiche la commande telle qu'elle serait exécutée, motifs développés, sans rien supprimer. C'est le meilleur réflexe avant un rm avec motif (leçon 4).

Où ranger Signalements

L'équipe a installé l'application ainsi, et chaque choix suit la FHS :

QuoiOùPourquoi
Le code et l'environnement Python/opt/signalements/Un logiciel additionnel livré en bloc, hors paquets de la distribution, dans son propre sous-répertoire
La configuration/etc/signalements/envPropre à la machine, à sauvegarder, modifiable sans toucher au code
L'état (photos jointes, si elles étaient stockées localement)/var/lib/signalements/Variable et persistant ; à sauvegarder
Les journauxjournald, consultable avec journalctl -u signalements (leçon 11)Journaux du service, centralisés par systemd ; un fichier irait dans /var/log/signalements/
L'unité systemd/etc/systemd/system/signalements.serviceConfiguration de service écrite par l'administrateur (les paquets installent les leurs dans /usr/lib/systemd/system/)

/usr/local aurait convenu pour un outil installé à la main ; /srv pour des fichiers servis tels quels (un site statique). Ce qui ne convient pas : le répertoire personnel de la personne qui a installé l'application (il disparaîtra avec son compte), ou /tmp (vidé régulièrement).

Voir les montages

$ findmnt /proc
TARGET SOURCE FSTYPE OPTIONS
/proc  proc   proc   rw,nosuid,nodev,noexec,relatime
$ findmnt /run
TARGET SOURCE FSTYPE OPTIONS
/run   tmpfs  tmpfs  rw,nosuid,nodev,noexec,relatime,size=3220628k,mode=755,inode64
$ df -h /

findmnt indique ce qui est monté à un endroit : /proc est un système de fichiers proc fabriqué par le noyau, /run un tmpfs, c'est-à-dire en mémoire (ce qui explique qu'il soit vide à chaque démarrage). Sans argument, findmnt affiche l'arbre complet des montages. df -h / affiche la taille, l'espace utilisé et l'espace libre du système de fichiers qui porte la racine, avec le périphérique qui le porte (/dev/sda1 ou /dev/vda1 sur beaucoup de machines virtuelles, /dev/nvme0n1p2 sur un disque NVMe). C'est la première commande à lancer quand une application se plaint de ne plus pouvoir écrire. df -h sans argument liste tous les systèmes de fichiers montés.

Sous le capot

Ce qu'est un répertoire. Sur un système de fichiers Unix (ext4, XFS, Btrfs), un fichier n'est pas son nom. Il est décrit par un inode (index node) : une structure numérotée qui contient le type, les permissions, le propriétaire, la taille, les dates, et l'emplacement des données sur le disque. Le nom n'est pas dans l'inode. Un répertoire n'est qu'un fichier spécial qui contient une table de correspondance entre des noms et des numéros d'inode. ls -i montre ce numéro (25456002 note.txt), et stat aussi.

Ce modèle explique beaucoup de choses que la leçon 4 exploite : renommer un fichier dans le même système de fichiers est instantané, quelle que soit sa taille (on change une ligne dans la table du répertoire, pas les données) ; un même inode peut avoir plusieurs noms (liens physiques, la colonne Links) ; et supprimer un fichier, c'est retirer un nom, les données n'étant libérées que lorsque plus aucun nom ni aucun processus n'y fait référence. Les permissions d'un répertoire (leçon 9) portent donc sur sa table de noms : pouvoir écrire dans un répertoire, c'est pouvoir y créer, renommer et supprimer des noms.

Comment le noyau suit un chemin. Pour ouvrir /etc/signalements/env, le noyau part de l'inode de la racine, lit sa table pour trouver le numéro de etc, lit la table de etc pour trouver signalements, et ainsi de suite, en vérifiant à chaque étape que vous avez le droit de traverser le répertoire. Il suit les liens symboliques rencontrés en chemin, et change de système de fichiers quand il traverse un point de montage. Un chemin relatif fait la même chose, en partant de l'inode du répertoire courant du processus.

Les systèmes de fichiers virtuels. /proc et /sys n'occupent aucun octet sur un disque. Le noyau répond aux lectures en fabriquant le contenu : /proc/<numéro>/ décrit chaque processus (leçon 10), /proc/meminfo la mémoire, /sys les périphériques et les pilotes. On peut parfois écrire dans certains de ces fichiers pour régler le noyau (c'est ce que fait la commande sysctl sur /proc/sys/). La page proc(5) est l'une des plus longues du manuel.

Pièges courants

Un script lancé « d'ailleurs » ne trouve plus ses fichiers. Il utilisait des chemins relatifs, valables depuis le répertoire où vous l'avez écrit. Lancé par systemd ou par une tâche planifiée, son répertoire courant est / ou le répertoire personnel de l'utilisateur. Chemins absolus dans tout ce qui s'exécute sans vous.

Le motif qui devient une option. Dans un répertoire qui contient un fichier nommé -rf ou -l, ls * ou rm * reçoivent ce nom comme premier argument, et le prennent pour une option. Écrivez ./* plutôt que * dans les commandes destructrices : chaque argument commence alors par ./.

Le motif qui ne correspond à rien. rm *.tmp dans un répertoire sans fichier .tmp passe le texte *.tmp à rm, qui répond qu'il n'existe pas. Sans gravité ici, mais dans un script, une boucle for f in *.tmp s'exécutera une fois avec la valeur littérale *.tmp. Le cours Bash pour l'automatisation présente l'option nullglob.

La taille d'un répertoire. Les 4 096 octets affichés par ls -l ne disent rien de son contenu. du -sh répertoire mesure ce qu'il occupe réellement.

Le disque plein qui ne l'est pas. df -h montre 100 % d'utilisation, mais du ne trouve pas les fichiers responsables : un fichier supprimé mais encore ouvert par un processus (un journal effacé à la main pendant que le service écrit dedans) continue d'occuper l'espace jusqu'à la fin du processus. La leçon 10 montre comment le retrouver. Et un df -h qui montre de l'espace libre alors que l'écriture échoue avec No space left on device peut signaler l'épuisement des inodes : df -i.

Confondre ~ et /root. Sous sudo -i, ~ désigne /root, pas votre répertoire personnel. Un fichier « déposé dans ~ » en tant que root n'est pas chez vous.

Sécurité

/etc contient les secrets de la machine. Fichier des mots de passe chiffrés (/etc/shadow), clés privées SSH du serveur (/etc/ssh/ssh_host_*_key), configuration des applications, parfois avec leurs mots de passe (/etc/signalements/env). Ses fichiers sensibles ne sont lisibles que par root ou par le service concerné ; vérifiez-le pour ceux que vous créez (leçon 9). Et quand vous sauvegardez /etc, la sauvegarde contient ces secrets : chiffrez-la.

/tmp est partagé. Tous les utilisateurs et tous les services peuvent y écrire. Un programme qui y crée un fichier au nom prévisible (/tmp/signalements.lock) peut être piégé par un autre utilisateur qui crée ce nom avant lui, par exemple sous forme de lien symbolique vers un fichier sensible. Le répertoire a une protection particulière (le sticky bit, le t de drwxrwxrwt, leçon 9) qui empêche de supprimer les fichiers des autres, mais pas ce genre de piège. Les programmes doivent créer leurs fichiers temporaires avec mktemp, et les services systemd peuvent recevoir un /tmp privé (PrivateTmp=yes, cours systemd en profondeur).

Les montages ont des options de sécurité. Dans la sortie de findmnt, nosuid, nodev et noexec interdisent sur ce système de fichiers, respectivement, les programmes à privilèges élevés (leçon 9), les fichiers de périphériques, et l'exécution de programmes. Monter /tmp ou un disque de données avec noexec empêche un attaquant d'y déposer puis d'y lancer un programme. Le cours Durcissement Linux en fait une mesure systématique.

Ne lancez pas un fichier inconnu. file d'abord. Un fichier facture.pdf peut être un script.

En production

  • Séparer les données de la racine. Sur les serveurs, /var/lib (bases de données, conteneurs) et parfois /var/log sont mis sur des volumes séparés, pour qu'une base qui grossit ou un journal qui s'emballe ne remplisse pas la partition système, et pour pouvoir agrandir, sauvegarder ou détacher ces données indépendamment (cours Le cloud : les fondamentaux).
  • Savoir quoi sauvegarder. /etc (configuration), /var/lib/<application> (état), les données servies dans /srv, et la liste des paquets installés. Pas /usr, /proc, /sys, /run, /tmp ni /dev, que l'on reconstruit ou qui n'existent qu'en mémoire.
  • Surveiller l'espace disque et les inodes, avec une alerte avant 100 % : un serveur au disque plein voit ses services échouer de façon souvent incompréhensible (base de données en lecture seule, journaux perdus, mises à jour impossibles).
  • Respecter les emplacements. Une application rangée selon la FHS est prévisible pour n'importe quel administrateur, et compatible avec les outils (sauvegardes, supervision, gestion de configuration). Chez Lyneko, les applications tournent en conteneurs sur Kubernetes, et la question se déplace : dans l'image, le code dans un répertoire dédié, la configuration et les secrets montés depuis l'extérieur, l'état dans des volumes ou des services managés. La logique de la FHS (séparer le statique, la configuration et le variable) y est la même.

Exercices

1. Se repérer sans ls (niveau 100). Sans lister de répertoire, dites dans quel répertoire vous chercheriez : (a) la configuration du serveur SSH ; (b) les fichiers de la base PostgreSQL installée par le paquet de la distribution ; (c) le programme ss ; (d) le journal des connexions et de sudo sur Ubuntu ; (e) la documentation fournie par le paquet openssh-server. Vérifiez ensuite.

Solution

(a) /etc/ssh/ (le fichier sshd_config et le répertoire sshd_config.d/). (b) /var/lib/postgresql/ (état variable et persistant ; la configuration est dans /etc/postgresql/ sur Debian et Ubuntu). (c) /usr/bin/ss (type ss), programme de la distribution, donc sous /usr. (d) /var/log/auth.log sur Ubuntu et Debian quand rsyslog est installé ; dans tous les cas, journalctl (leçon 11). (e) /usr/share/doc/openssh-server/.

2. Absolu ou relatif (niveau 100). Vous êtes dans /var/log. Écrivez le chemin relatif puis le chemin absolu vers : (a) /var/lib/signalements ; (b) /etc/signalements/env ; (c) votre répertoire personnel. Lequel utiliseriez-vous dans l'unité systemd de Signalements ?

Solution

(a) ../lib/signalements et /var/lib/signalements. (b) ../../etc/signalements/env et /etc/signalements/env. (c) ../../home/camille, /home/camille, ou ~. Dans une unité systemd, toujours le chemin absolu : le répertoire courant d'un service n'est pas /var/log, et systemd exige d'ailleurs des chemins absolus pour la plupart de ses directives.

3. Lire une ligne de ls (niveau 100). Interprétez chaque champ : drwxrwxrwt 160 root root 57344 Oct 5 11:16 /tmp. Que signifie le t final, et pourquoi ce répertoire a-t-il 160 liens ?

Solution

d : répertoire. rwxrwxrwx avec un t en dernière position : tout le monde peut lire, écrire et traverser, et le sticky bit est positionné, ce qui interdit de supprimer ou renommer les fichiers des autres (leçon 9). 160 : nombre de liens, soit 158 sous-répertoires plus . et l'entrée tmp dans /. root root : propriétaire et groupe. 57344 : taille de la table des noms du répertoire (elle a grandi avec le nombre d'entrées, et ne rétrécit pas forcément). La date est celle de la dernière modification de cette table, c'est-à-dire de la dernière création, suppression ou renommage d'un fichier dans /tmp.

4. Prévoir l'expansion (niveau 100). Dans un répertoire qui contient a.log, b.log, .c.log et d.txt, dites ce qu'affiche chaque commande avant de la lancer : echo *.log, echo ?.*, echo [ab].log, echo *.csv, echo {a,z}.log, echo .*.log.

Solution

a.log b.log (le fichier caché est exclu) ; a.log b.log d.txt (? ne correspond pas au point initial de .c.log) ; a.log b.log ; *.csv (aucune correspondance, motif laissé tel quel) ; a.log z.log (les accolades génèrent du texte, z.log n'a pas besoin d'exister) ; .c.log (un motif qui commence explicitement par un point correspond aux fichiers cachés).

Récapitulatif

  • Une seule arborescence, une racine / ; disques et partitions y sont montés. Les noms sont sensibles à la casse.
  • La FHS donne une place à chaque chose : /etc la configuration, /usr les programmes de la distribution, /usr/local et /opt ce qui vient d'ailleurs, /var/lib l'état, /var/log les journaux, /home les utilisateurs, /tmp et /run le temporaire, /proc et /sys le noyau.
  • Sur Debian et Ubuntu, /bin, /sbin et /lib sont des liens vers /usr (fusion de /usr).
  • Chemins absolus (depuis /) et relatifs (depuis le répertoire courant, avec . et ..) ; ~ pour le répertoire personnel ; cd - pour revenir. Dans les scripts et les services : absolus.
  • ls -l : type et permissions, liens, propriétaire, groupe, taille, date de modification, nom. -a, -h, -t, -r, -d, -R, -i.
  • Le type d'un fichier se lit dans le premier caractère de ls -l ; file regarde le contenu ; stat donne toutes les métadonnées.
  • Le shell développe *, ? et [...] en noms de fichiers existants ; les accolades génèrent du texte. echo avant rm.
  • Un répertoire est une table nom vers inode ; le nom n'est pas dans le fichier.

Pour aller plus loin

  • man 7 hier et man 7 file-hierarchy : la carte de l'arborescence, telle que les distributions actuelles la pratiquent.
  • La FHS 3.0 elle-même, courte et lisible, en particulier le chapitre 2 sur les catégories statique, variable, partageable.
  • man 7 inode, pour la liste exacte de ce que contient un inode.
  • La leçon suivante, qui crée, copie, déplace, lie et supprime des fichiers, et montre ce que ces opérations font aux inodes.
Voir ma constellation →

Sources