Linux sans magie #54 — Inodes épuisés : pourquoi il reste de l’espace mais plus de fichiers

Diagnostiquer une saturation des inodes sous Linux avec df -i, du --inodes et find, distinguer ext4 de XFS et agir sans supprimer de fichiers à l’aveugle.

Un service ne parvient plus à créer de fichiers temporaires. Le message No space left on device s'affiche, mais df -h indique encore plusieurs gigaoctets libres. Faut-il agrandir le disque ? Supprimer des fichiers volumineux ? Pas avant d'avoir vérifié les inodes.

Dans le #52, nous avons distingué la saturation des blocs et celle des inodes. Cet article approfondit ce deuxième scénario : comprendre ce qui manque réellement, localiser les arborescences qui consomment les inodes, identifier le processus responsable et corriger le problème sans effacer de données utiles.

Comprendre l'inode et l'erreur ENOSPC

Sur de nombreux filesystems Unix, un inode décrit un objet : type, permissions, propriétaire, taille, horodatages et références aux blocs. Les noms sont enregistrés dans les répertoires, qui associent les noms aux numéros d'inode.

Un même inode peut être référencé par plusieurs noms via des liens matériels. Un répertoire consomme lui aussi un inode, tandis qu'un lien symbolique représente un objet distinct. Il serait donc inexact d'affirmer que « un nom de fichier = un inode » dans tous les cas.

Un filesystem a besoin de ressources pour créer de nouveaux objets. Si aucune nouvelle allocation d'inode n'est possible, la création peut échouer avec ENOSPC même lorsqu'il reste des blocs de données libres.

Filesystem ext4 de laboratoire
  Capacité en blocs : 20 Go
  Espace libre      : 8 Go     ← df -h paraît rassurant
  Inodes totaux     : 100 000
  Inodes utilisés   : 100 000  ← df -i révèle le problème
  Inodes libres     : 0

Résultat possible : impossible de créer un nouveau fichier.

Ces valeurs sont illustratives, non issues d'un test réel. Une application peut également rencontrer ENOSPC à cause d'un quota, d'une limite de plateforme ou d'une autre ressource. La vérification du filesystem reste indispensable.

Pourquoi certains filesystems s'épuisent en inodes

Ext4 réserve généralement un nombre d'inodes déterminé lors de la création du filesystem. L'équilibre entre capacité et nombre d'inodes dépend de paramètres de formatage, dont le ratio octets/inode. Une charge composée d'innombrables petits fichiers peut consommer les inodes avant les blocs disponibles.

Les exemples fréquents sont les sessions web non purgées, un cache sans politique de rétention, des millions de fichiers temporaires, un spool de messagerie, des exports fragmentés ou un logiciel qui crée un fichier de log à chaque requête.

XFS fonctionne différemment : il alloue les inodes dynamiquement en fonction des besoins et de l'espace admissible. Son compte d'inodes peut varier ; ne déduisez pas d'un simple pourcentage df -i que la solution ext4 s'applique à XFS. Sur XFS, l'allocation d'inodes peut rencontrer d'autres limites ou contraintes internes. La stratégie d'investigation doit tenir compte du type exact de filesystem.

Étape 1 — Vérifier le bon point de montage

Lorsque l'application échoue dans /var/lib/monapp/cache, ne diagnostiquez pas d'abord la racine / par habitude :

df -hT /var/lib/monapp/cache
df -i /var/lib/monapp/cache
findmnt --target /var/lib/monapp/cache -o SOURCE,TARGET,FSTYPE,OPTIONS
lsblk -f

Adaptez le chemin à un répertoire existant de votre service. Si /var/lib possède un montage distinct de /var, seul le bon point de montage permet un diagnostic cohérent.

Les colonnes de df -i correspondent typiquement à Inodes, IUsed, IFree et IUse%. Sur un ext4 avec IFree=0, l'hypothèse d'épuisement des inodes est forte. À l'inverse, un IUse% modéré suggère de rechercher une autre cause.

Notez simultanément la consommation des blocs et celle des inodes. Les deux ressources peuvent être saturées ; ce ne sont pas des diagnostics exclusifs.

Étape 2 — Localiser l'arborescence à forte densité de fichiers

Sur GNU Coreutils, du sait compter l'usage des inodes au lieu de mesurer la taille en blocs :

sudo du --inodes -x -d1 /var
sudo du --inodes -x -d1 /var/lib

L'option --inodes passe au comptage des objets, -d1 limite l'affichage à un niveau et -x évite de descendre dans un autre filesystem. Un sous-répertoire à plusieurs centaines de milliers d'objets ressortira même si sa taille exprimée en gigaoctets est faible.

Important : choisissez un point de départ appartenant au filesystem saturé. Si /var/lib est un montage distinct, le comptage de /var ne doit pas être confondu avec celui du montage enfant. Les hard links, bind mounts et particularités des filesystems influencent les comptages : du --inodes est un indicateur de localisation, pas un inventaire comptable universel.

Une exploration récursive peut produire beaucoup d'opérations de lecture de métadonnées. Sur un serveur très chargé, limitez la profondeur et le périmètre plutôt que de scanner simultanément tous les volumes.

Étape 3 — Examiner les producteurs de fichiers avec find

Après avoir repéré un dossier suspect, find permet de compter les fichiers réguliers d'un sous-arbre :

sudo find /var/lib/monapp/cache -xdev -type f -printf '.' | wc -c

Cette commande n'efface rien. Elle imprime un caractère par fichier régulier et compte les caractères générés. Les répertoires, liens symboliques et autres types d'objets ne sont pas inclus : le résultat n'est donc pas égal au nombre total d'inodes utilisés. L'option -printf est spécifique à GNU findutils.

Pour chercher une explosion récente, examinez une période précise :

sudo find /var/lib/monapp/cache -xdev -type f -mmin -120 -print

-mmin -120 sélectionne les fichiers dont le contenu a été modifié récemment ; cela ne prouve pas que le fichier a été créé durant cette période. Ne confondez pas mtime, ctime et date de création. La commande peut produire une sortie immense : travaillez sur un sous-dossier ciblé et évitez de rediriger la sortie sur le filesystem saturé.

Pour recouper les dates, droits et propriétaires d'un fichier identifié :

stat /var/lib/monapp/cache/fichier-exemple

Le chemin est fictif. Ne présumez pas que tous les fichiers de ce répertoire peuvent être supprimés : une application peut en avoir besoin même s'ils sont petits ou anciens.

Étape 4 — Identifier le service responsable

La concentration d'inodes fournit un indice, pas nécessairement la cause. Reliez le répertoire à son propriétaire, à l'application et aux événements de maintenance :

ls -ld /var/lib/monapp /var/lib/monapp/cache
journalctl --since "2 hours ago" --no-pager
findmnt --target /var/lib/monapp/cache

La lecture de journaux peut nécessiter des droits, et un journal partiellement indisponible n'invalide pas l'hypothèse. Cherchez une tâche périodique bloquée, une rotation inactive, une anomalie de création de sessions, un changement de version applicative ou un processus qui génère trop de fichiers.

Dans un conteneur, vérifiez le point de montage tel qu'il est vu par le processus. Un overlay, une limite de volume, un quota projet ou un montage réseau peut produire un comportement différent du simple filesystem local de l'hôte.

Un quota d'inodes dépassé peut empêcher un utilisateur de créer des fichiers alors que df -i global indique encore des inodes disponibles. Dans ce cas, la recherche doit porter sur les quotas applicables au compte, au groupe ou au projet.

Distinguer les scénarios sans raccourci

ObservationInterprétation possibleVérification suivante
df -h : blocs libres ; df -i : IFree=0 sur ext4Inodes épuisésdu --inodes sur le montage concerné
df -h : 100 % utilisé ; df -i : libreSaturation des blocsMéthode du #52 avec du et lsof
Les deux sont proches de 100 %Double saturationIdentifier les consommateurs des deux ressources
df -i indique des inodes libres, création refuséeQuota ou autre limite possibleConfiguration des quotas, journaux et contexte du processus
XFS avec compte d'inodes variableAllocation dynamiqueExaminer type de filesystem et limites XFS propres à l'hôte

Ce tableau oriente le diagnostic : il ne remplace pas la vérification des contraintes applicatives et de stockage réelles.

Remédiation : agir sur le générateur, pas sur des fichiers au hasard

La première mesure doit être validée par le propriétaire du service. Une correction peut consister à rétablir la rotation de sessions, limiter une génération excessive, appliquer la politique de purge du produit ou déplacer des fichiers conservés vers un espace conçu pour leur archivage.

Évitez les recettes du type find ... -delete ou rm -rf /var/lib/... : elles peuvent détruire des sessions actives, des fichiers métiers, des preuves d'incident ou des objets attendus par l'application. Un fichier plus ancien qu'un délai arbitraire n'est pas automatiquement supprimable.

Un nettoyage réellement sûr suit cette séquence :

  1. confirmer la source et la fonction des fichiers ;
  2. valider la politique de rétention et l'existence d'une sauvegarde restaurable ;
  3. choisir l'outil de purge officiel de l'application ;
  4. réaliser l'intervention pendant une fenêtre approuvée si elle présente un risque ;
  5. vérifier que le nombre d'inodes libres remonte et que le service recrée correctement ses fichiers.

En cas d'épuisement récurrent, revoyez les durées de conservation, les batchs, les caches et le dimensionnement, plutôt que de multiplier des suppressions manuelles.

Faut-il agrandir le filesystem ?

Un agrandissement peut être pertinent, mais il ne s'agit pas d'une réponse universelle. Pour ext4, le nombre d'inodes disponibles dépend de la configuration et des structures du filesystem ; une extension peut augmenter les ressources disponibles selon les caractéristiques du volume. Une modification en production exige un plan de capacité, une sauvegarde et une procédure adaptée à la pile disque, LVM ou RAID.

Pour XFS, le nombre d'inodes évolue différemment ; ses limites d'allocation et de configuration ne doivent pas être traitées comme un simple « quota fixe ext4 ». Ne reformatez jamais un filesystem pour changer le ratio d'inodes sans stratégie explicite de migration, sauvegarde et restauration.

Aucune commande d'extension, de formatage ou de réparation n'est exécutée dans ce guide.

Vérifier le retour à la normale

Après une action approuvée, recommencez sur le même point de montage :

df -hT /var/lib/monapp/cache
df -i /var/lib/monapp/cache
sudo du --inodes -x -d1 /var/lib
journalctl --since "20 minutes ago" --no-pager

Le nombre d'inodes libres doit redevenir compatible avec les créations attendues. Contrôlez également les blocs libres, la progression des journaux et l'état du service. Enfin, faites réaliser une création de fichier contrôlée par l'application, dans un chemin validé, plutôt que de déposer un fichier de test au hasard.

Si les inodes sont à nouveau consommés en quelques minutes, la cause n'est pas résolue : recherchez le processus qui produit ces objets et corrigez sa configuration ou son dysfonctionnement.

Bonnes pratiques, sécurité et limites

Supervisez simultanément l'utilisation des blocs et des inodes, et adaptez les seuils au taux de croissance. Sur les applications qui génèrent de nombreux fichiers, surveillez aussi le nombre d'objets créés par unité de temps et les erreurs de création.

Les commandes GNU utilisées ici ne sont pas toutes disponibles sur d'autres Unix. Les différences entre ext4 et XFS, les contraintes d'overlayfs, les quotas, les permissions et les espaces de noms des conteneurs peuvent exiger une méthode spécifique. Ne concluez pas à une saturation d'inodes à partir du seul message ENOSPC.

Le diagnostic proposé est volontairement non destructeur. Aucun test de saturation réel, aucune création massive de fichiers ni aucune purge n'ont été effectués pour cet article.

Retour arrière et traçabilité

Les commandes présentées servent à observer l'état et ne nécessitent pas de rollback des données. Une purge ou une modification de configuration ultérieure doit disposer de sa propre procédure de retour arrière, fondée sur les sauvegardes et le comportement de l'application.

Conservez dans le compte rendu l'état initial df -h et df -i, les chemins concernés, la cause identifiée, l'intervention autorisée et les mesures de surveillance mises en place.

Références officielles

Conclusion

Un message No space left on device n'implique pas forcément l'absence de blocs libres. Avec df -i, localisez d'abord le filesystem et confirmez l'épuisement des inodes. du --inodes aide ensuite à trouver l'arborescence dominante, et find permet d'examiner les objets et leur évolution.

La correction durable consiste à maîtriser la création et la rétention des fichiers, pas à supprimer au hasard. Dans le #55, nous aborderons la vérification et la réparation des filesystems Linux avec fsck et e2fsck, ainsi que leurs risques.