L'arborescence et les chemins
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épertoire | Ce qu'il contient | Sur sig-app-1 |
|---|---|---|
/etc | La configuration propre à la machine, en fichiers texte | /etc/ssh/sshd_config, /etc/signalements/ |
/usr | Les 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/local | La même chose pour ce que l'administrateur installe à la main, hors paquets | Un outil compilé localement |
/opt | Les logiciels additionnels livrés en un bloc, un sous-répertoire par logiciel | /opt/signalements/ |
/var | Les données variables : ce qui change pendant le fonctionnement | |
/var/log | Les journaux | /var/log/syslog, /var/log/auth.log, /var/log/journal/ |
/var/lib | L'état persistant des programmes | /var/lib/postgresql/, /var/lib/docker/ |
/var/cache, /var/tmp | Caches reconstructibles ; fichiers temporaires qui survivent au redémarrage | |
/srv | Les données servies par la machine (sites, fichiers) | |
/home | Les répertoires personnels des utilisateurs | /home/camille |
/root | Le répertoire personnel de root, hors de /home | |
/tmp | Les fichiers temporaires, effacés au redémarrage ou périodiquement | |
/run | Les données d'exécution (numéros de processus, sockets), en mémoire, vidées à chaque démarrage | /run/systemd/journal/socket |
/boot | Le noyau et les fichiers du chargeur d'amorçage | /boot/vmlinuz-... |
/dev | Les fichiers de périphériques | /dev/null, /dev/sda |
/proc, /sys | Des systèmes de fichiers virtuels fabriqués par le noyau | /proc/version (leçon 1) |
/mnt, /media | Points 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ère | Type | Exemple |
|---|---|---|
- | Fichier ordinaire | /etc/os-release (sa cible, plus exactement) |
d | Répertoire | /etc |
l | Lien symbolique, qui pointe vers un autre chemin | /bin -> usr/bin |
c | Périphérique en mode caractère (flux d'octets) | /dev/null, /dev/urandom |
b | Périphérique en mode bloc (disque) | /dev/sda, /dev/nvme0n1 |
s | Socket : point de communication entre processus | /run/systemd/journal/socket |
p | Tube 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 ; deuxcd -successifs font l'aller-retour entre deux répertoires, très pratique entre la configuration et les journaux d'un service.cdsans argument ramène au répertoire personnel, commecd ~.
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,lsaffiche 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.4Mpour 2 500 000 octets, parce quelscompte en puissances de 1 024 (2 500 000 / 1 048 576 ≈ 2,38).--siutilise les puissances de 1 000.-t: tri par date de modification, le plus récent en premier.ls -ltrinverse 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...-Ales affiche sans.ni...-d: affiche le répertoire lui-même au lieu de son contenu.ls -l /etcliste les fichiers de/etc;ls -ld /etcaffiche 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érezfind(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 :
| Quoi | Où | 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/env | Propre à 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 journaux | journald, 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.service | Configuration 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/logsont 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,/tmpni/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 :
/etcla configuration,/usrles programmes de la distribution,/usr/localet/optce qui vient d'ailleurs,/var/libl'état,/var/logles journaux,/homeles utilisateurs,/tmpet/runle temporaire,/procet/sysle noyau. - Sur Debian et Ubuntu,
/bin,/sbinet/libsont 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;fileregarde le contenu ;statdonne toutes les métadonnées. - Le shell développe
*,?et[...]en noms de fichiers existants ; les accolades génèrent du texte.echoavantrm. - Un répertoire est une table nom vers inode ; le nom n'est pas dans le fichier.
Pour aller plus loin
man 7 hieretman 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.
Sources
- Filesystem Hierarchy Standard 3.0 (Linux Foundation, 2015)
- man-pages, hier(7) : description de la hiérarchie du système de fichiers
- man-pages, file-hierarchy(7) (systemd)
- Debian Wiki, UsrMerge
- GNU Coreutils, ls invocation
- GNU Bash Reference Manual, Filename Expansion et Brace Expansion
- man-pages, inode(7) et proc(5)
- W. Shotts, The Linux Command Line (No Starch Press, 2e édition, 2019), chapitres 2 à 4