Linux sans magie #52 — Diagnostiquer un disque plein sous Linux
Identifier la cause d’un filesystem saturé avec df, du, find et lsof, distinguer espace et inodes, et libérer de la place sans suppression risquée.
Après le chiffrement LUKS du #51, revenons à un incident très concret : une application ne peut plus écrire, un service échoue à démarrer et un message No space left on device apparaît dans les journaux. Le réflexe est parfois de supprimer les plus gros fichiers trouvés. C'est précisément ce qu'il faut éviter avant d'avoir identifié quel filesystem est saturé, pourquoi et qui utilise encore les données.
Avec df, du, find et lsof, on peut construire un diagnostic progressif, en commençant par des commandes non destructrices. L'objectif est de restaurer le service sans masquer la cause ni provoquer une perte de données.
Comprendre l'incident avant d'agir
Imaginons un serveur Linux dont l'application écrit ses journaux dans /var/log/monapp et conserve ses fichiers dans /srv/app. Une alerte de supervision indique que l'espace disponible est presque nul. Le système peut avoir plusieurs volumes, points de montage et espaces temporaires :
/ → filesystem du système
/var → éventuellement un autre filesystem
/srv/app → éventuellement un LV distinct
/var/log → parfois un montage dédié
/tmp → parfois un tmpfs en mémoire
Supprimer un fichier sur /srv/app ne libère rien sur le filesystem de /var/log s'ils sont distincts. De la même façon, un dossier visible sous un point de montage ne signifie pas qu'il appartient au même filesystem que sa racine apparente.
Deux saturations doivent être distinguées : manque de blocs disponibles et épuisement des inodes. La première se produit quand les blocs de données ne suffisent plus ; la seconde quand un filesystem ne peut plus créer de nouvelles entrées, parfois malgré une capacité en octets encore disponible.
Étape 1 — Localiser le filesystem réellement saturé
Commencez sans modifier le stockage :
df -hT
df -hT /var/log/monapp
df -i /var/log/monapp
findmnt --target /var/log/monapp -o SOURCE,TARGET,FSTYPE,OPTIONS
lsblk -f
df -hT affiche la capacité, l'occupation et le type des filesystems montés. Lorsqu'on lui donne un chemin, df rapporte le filesystem qui contient ce chemin, et non la taille du répertoire. df -i affiche l'usage des inodes : c'est un contrôle indispensable face à un message No space left on device.
findmnt vérifie le point de montage associé au chemin observé ; lsblk aide à identifier les couches bloc. Attention : df peut également afficher des montages réseau, des filesystems temporaires ou des overlays de conteneurs. Il faut diagnostiquer le bon espace, pas forcément celui qui a le pourcentage le plus spectaculaire.
Relevez la valeur Avail, le point de montage, le nom du périphérique et la date de l'alerte. Un espace à 100 % peut empêcher certains services d'écrire ou de tourner, mais il reste à comprendre la cause.
Étape 2 — Repérer les répertoires consommateurs avec du
Une fois le point de montage établi, explorez-le en lecture seule. Si le problème concerne le filesystem monté sur /var :
sudo du -xhd1 /var
sudo du -xhd1 /var/log
-h rend les tailles lisibles, -d1 limite la profondeur d'affichage à un niveau et -x évite de descendre dans un filesystem différent de celui du chemin de départ. Sur GNU coreutils, ces options facilitent la recherche d'un sous-répertoire consommateur sans mélanger les montages.
Le calcul peut être lent et générer des lectures d'entrées de répertoire importantes sur un système chargé. Ne lancez pas plusieurs balayages complets en parallèle pendant un incident sensible. Certaines arborescences peuvent être inaccessibles sans privilèges ; des erreurs de permission rendent les totaux incomplets.
Il faut comparer des périmètres identiques. Un du /var lancé alors qu'un autre filesystem est monté sous /var/lib peut additionner des données qui ne figurent pas dans le df du filesystem de /var. L'option -x limite ce piège pour les systèmes de fichiers distincts, même si les bind mounts, reflinks, snapshots et autres mécanismes de stockage peuvent compliquer le comptage.
Étape 3 — Rechercher les gros fichiers avec find
Si du révèle un sous-répertoire anormalement volumineux, find peut identifier les fichiers de taille apparente élevée.
sudo find /var/log -xdev -type f -size +500M -printf '%s %p\n'
Ce filtre recherche des fichiers réguliers dont la taille apparente est supérieure à environ 500 MiB, avec leur nombre d'octets et leur chemin. Les options -xdev et -size suivent la documentation GNU findutils ; -printf est également une extension GNU. Le résultat peut être volumineux : ciblez d'abord le sous-répertoire identifié par du.
Un fichier de plusieurs gigaoctets n'est pas automatiquement responsable d'autant de blocs réellement occupés. Les fichiers sparse possèdent des zones logiques qui peuvent ne pas consommer de blocs physiques. Sur des filesystems modernes, compression, partage de blocs ou Copy-on-Write compliquent encore la relation entre taille apparente et occupation réelle.
Pour approfondir un fichier précis :
stat /var/log/monapp/monapp.log
du -h /var/log/monapp/monapp.log
Ne supprimez pas automatiquement tous les fichiers trouvés par find. Un gros fichier peut être une base de données, une image disque, une archive réglementaire ou un journal encore utilisé.
Étape 4 — Quand df et du ne sont pas d'accord
Un cas classique : df annonce le filesystem presque plein, mais du n'explique qu'une partie de la capacité utilisée. Ce n'est pas nécessairement une anomalie.
df mesure l'occupation au niveau du filesystem ; du parcourt des fichiers et répertoires encore visibles. Ils ne mesurent donc pas exactement la même chose. Plusieurs explications sont possibles :
- un processus garde ouvert un fichier qui a déjà été supprimé ;
- des métadonnées et blocs réservés occupent de la capacité ;
- le périmètre analysé par
dune correspond pas au filesystem mesuré pardf; - les mécanismes de snapshots, de partage de blocs ou de compression modifient l'interprétation des chiffres ;
- des fichiers cachés par un point de montage peuvent subsister sur le filesystem sous-jacent.
Les blocs réservés d'ext4, par exemple, peuvent faire que Size ne correspond pas simplement à Used + Avail pour un utilisateur non privilégié. Une différence entre df et du n'autorise aucune suppression à l'aveugle.
Étape 5 — Identifier les fichiers supprimés mais toujours ouverts
Linux libère normalement les blocs d'un fichier seulement lorsqu'il n'existe plus de liens pertinents et qu'aucun processus ne conserve encore le fichier ouvert. Un journal supprimé peut donc continuer à occuper le disque si l'application y écrit toujours via son descripteur.
Sur une machine où lsof est installé :
sudo lsof +L1
L'option +L1 sélectionne les fichiers ouverts dont le nombre de liens est inférieur à un, généralement des fichiers déjà supprimés. Examinez le processus, son PID, le type de fichier et le périphérique. Vérifiez qu'il s'agit bien du filesystem saturé ; tous les fichiers signalés ne concernent pas le montage recherché.
Le choix de la correction dépend du service. Dans certains cas, un redémarrage propre, planifié et validé de l'application ferme le descripteur et libère enfin l'espace. Mais redémarrer une base de données, un composant critique ou un service non redondé peut provoquer une interruption ; il faut suivre sa procédure d'exploitation.
N'écrivez pas directement dans /proc/<PID>/fd/<N> pour « vider » un journal sans comprendre l'application et les effets de l'opération. La fermeture ou rotation officielle du fichier est préférable. Si lsof n'est pas installé, son absence n'est pas une preuve qu'aucun fichier supprimé n'est encore ouvert.
Étape 6 — Vérifier l'épuisement des inodes
Un filesystem peut refuser de nouveaux fichiers malgré plusieurs gigaoctets disponibles. Consultez :
df -i
df -i /var/log/monapp
Sur un filesystem doté d'un nombre fini d'inodes, un IUse% proche de 100 % suggère une accumulation de très nombreux petits fichiers. Des caches applicatifs, sessions, spools ou systèmes de génération de fichiers peuvent en être responsables.
Pour évaluer une arborescence sur GNU coreutils :
sudo du --inodes -x -d1 /var
Ce résultat aide à localiser les sous-répertoires consommant de nombreuses entrées. La pertinence de ces indicateurs dépend du filesystem : certains systèmes allouent les inodes dynamiquement ou présentent des métriques particulières. Si l'épuisement des inodes est confirmé, ne supprimez pas arbitrairement des fichiers métiers. Identifiez d'abord leur provenance et leur politique de rétention.
Le #54 traitera spécifiquement les inodes ; ici, l'objectif est de ne pas confondre ce diagnostic avec une pénurie de blocs.
Choisir un nettoyage réellement sûr
À ce stade, vous devez avoir identifié le bon filesystem, les répertoires concernés et, si nécessaire, les processus qui gardent des fichiers ouverts. La remédiation dépend de la cause.
| Cause confirmée | Intervention à privilégier |
|---|---|
| Journaux applicatifs actifs | Rotation ou purge documentée par l'application, avec conservation adaptée |
| Journaux systemd | Vérifier l'occupation puis appliquer la politique de rétention journald |
| Fichiers supprimés encore ouverts | Fermeture ou redémarrage contrôlé du service concerné |
| Cache applicatif | Nettoyage via la commande ou API officielle de l'application |
| Croissance légitime des données | Étudier l'extension de la capacité, la rétention et l'archivage |
| Inodes saturés | Diagnostiquer le générateur des petits fichiers et leur cycle de vie |
Ne lancez pas un rm -rf générique dans /var, /tmp ou /var/log sur un système actif. Une suppression peut rompre des services, effacer des preuves d'incident ou contrevenir à la rétention attendue.
Pour journald, préférez par exemple une consultation non destructive de l'occupation :
journalctl --disk-usage
La réduction de rétention via journalctl --vacuum-... nécessite une décision d'exploitation : elle supprime des journaux archivés et peut compromettre une investigation. Les journaux actifs et archivés ne sont pas gérés de la même manière.
Vérifier après intervention
Après une correction approuvée et exécutée par l'exploitant, vérifiez la capacité sur le même point de montage qu'au début :
df -hT /var/log/monapp
df -i /var/log/monapp
findmnt --target /var/log/monapp -o SOURCE,TARGET,FSTYPE
journalctl -k --since "20 minutes ago" --no-pager
La valeur Avail doit s'être améliorée dans le filesystem ciblé ; la hausse de place libre doit être cohérente avec ce qui a été fermé, archivé ou nettoyé. Contrôlez également les journaux applicatifs, les nouveaux fichiers créés, l'état des services et la disparition des alertes.
Un df revenu à un niveau normal ne garantit pas que la cause est corrigée. Si le service recrée immédiatement les mêmes volumes de logs ou de données, le disque se remplira à nouveau.
Bonnes pratiques, sécurité et limites
Avant l'incident, configurez des alertes sur les blocs et les inodes, des seuils tenant compte du rythme de croissance, une rotation de journaux testée et un suivi des volumes critiques. Documentez les montages, leurs propriétaires applicatifs et leurs règles de rétention.
En cas de disque plein, limitez les opérations qui génèrent de nouvelles écritures : journaux de diagnostic volumineux, copies de répertoires et archives sur le même filesystem peuvent aggraver la situation. Les commandes de balayage en lecture seule ont elles-mêmes un coût d'I/O ; choisissez le périmètre le plus restreint possible.
Les fichiers distants, conteneurs, overlays, quotas, snapshots, thin pools et stockages distribués demandent parfois des outils et métriques propres à leur architecture. Une erreur ENOSPC n'est pas toujours une simple saturation du disque physique : vérifiez les quotas et les limites de la plateforme lorsque df ne suffit pas.
Retour arrière
Pour les étapes de diagnostic présentées, aucun rollback de stockage n'est nécessaire : elles sont conçues pour observer sans supprimer. Pour une opération de nettoyage ultérieure, la possibilité de revenir en arrière dépend des données supprimées ou du service redémarré. Avant toute suppression, confirmez l'existence d'une sauvegarde restaurable et le périmètre exact des fichiers concernés.
Si une suppression inappropriée a lieu, arrêtez les écritures non indispensables et engagez une procédure de récupération ; ne poursuivez pas les essais de nettoyage pour tenter de « compenser » une erreur.
Références officielles
- GNU Coreutils — df : occupation des filesystems
- GNU Coreutils — du : occupation des arborescences
- GNU Coreutils — Pourquoi df et du diffèrent
- GNU Findutils — tailles et sélection des fichiers
- lsof(8) — fichiers ouverts, option +L1
Conclusion
Pour diagnostiquer un disque plein sous Linux, commencez par df pour choisir le filesystem, poursuivez avec du pour identifier les répertoires, puis find pour cibler les fichiers. Si les chiffres ne correspondent pas, lsof +L1 peut révéler des fichiers supprimés mais toujours ouverts. Vérifiez enfin les inodes et les montages avant toute décision de nettoyage.
La méthode est simple : localiser, expliquer, décider, vérifier. Dans le #53, nous poursuivrons avec le diagnostic d'un filesystem passé en lecture seule, symptôme qui réclame lui aussi de ne pas agir dans la précipitation.
