Pourquoi df et du divergent : Découvrir les gigaoctets cachés sur Linux
La commande df -h indique 95 % d'utilisation du disque, tandis que du -sh /* ne totalise que 20 %. Les 75 % restants sont invisibles pour du mais occupent des blocs de disque. La raison en est les descripteurs de fichiers ouverts par des processus pointant vers des fichiers supprimés. df lit directement le superbloc du système de fichiers, du parcourt l'arborescence des répertoires et ignore les fichiers sans entrée dedans.
Un inode stocke les métadonnées du fichier, y compris la liste des blocs de données. rm ne supprime que l'entrée du répertoire (lien physique), le compteur de liens de l'inode diminue, mais si un processus détient un descripteur, les blocs restent alloués.
Diagramme :
Avant rm :
répertoire inode blocs
/var/log/ --> app.log --> [bloc1][bloc2]
^
descripteur nginx (pid 1234, fd 7)
Après rm :
répertoire inode blocs
/var/log/ --> (supprimé) --> [bloc1][bloc2]
^
descripteur nginx
du ne voit pas le fichier dans /var/log/, df enregistre les blocs occupés.
Cas classiques du problème
Rotation des logs : logrotate effectue rm sur un ancien fichier, mais nginx ou java détient un descripteur depuis le démarrage. Le processus écrit dans le fichier supprimé, df enregistre une utilisation accrue, du non.
Autres scénarios :
- Démon à longue durée de vie avec des logs ouverts.
- Bogues dans les scripts de nettoyage où rm précède la fermeture du descripteur.
- Conteneurs Docker où des processus internes détiennent des fichiers de l'hôte.
Le problème s'accumule : des gigaoctets disparaissent sans être remarqués jusqu'à ce que le disque soit plein.
Trouver les processus avec des fichiers supprimés
Utilisez lsof +L1 pour les fichiers avec NLINK < 1 (supprimés du système de fichiers mais ouverts) :
COMMANDE PID UTILISATEUR FD TYPE PÉRIPHÉRIQUE TAILLE/OFFSET NLINK NŒUD NOM
nginx 1234 www 7w REG 8,1 2147483648 0 12345 /var/log/app.log (supprimé)
java 5678 app 3w REG 8,1 536870912 0 67890 /var/log/service.log (supprimé)
Champs clés :
- COMMANDE/PID : processus et identifiant.
- FD : descripteur (7w — écriture, numéro 7).
- TAILLE/OFFSET : taille — source des Go perdus.
- NLINK=0 : confirmation de la suppression.
- NOM (supprimé) : chemin avant rm.
Filtre de taille : lsof +L1 | awk '$7 > 104857600 {print}' (fichiers >100 Mo).
Libérer de l'espace sans redémarrer
Pour le processus PID 1234, FD 7 :
$ > /proc/1234/fd/7
/proc est procfs en mémoire. La commande met le fichier à zéro via le descripteur, le noyau libère les blocs instantanément. df se met à jour, le processus continue d'écrire dans fd 7.
Vérification : lsof +L1 | grep 1234 — TAILLE/OFFSET=0 ou vide.
Automatisation par script :
#!/bin/bash
lsof +L1 | awk '$7 > 104857600 && $9 ~ /supprimé/ {print $2, $8}' | while read pid fd; do
echo "Mise à zéro de $pid/$fd"
> /proc/$pid/fd/$fd
echo "Espace libéré"
done
Prévenir le problème dans logrotate
Évitez rm dans la rotation. Dans /etc/logrotate.d/app :
/var/log/app.log {
quotidien
rotation 7
compression
copytruncate
}
copytruncate copie le log, puis tronque l'original (mécanisme >). Le descripteur ne change pas.
Inconvénient : micro-délai de copie — perte possible de lignes.
Alternative sans perte :
- logrotate : mv ancien → nouveau fichier.
- kill -HUP <pid> (SIGHUP pour réouverture des logs).
nginx : nginx -s reopen. systemd : systemctl reload nginx.
Surveillance et alertes
Script de vérification :
lsof +L1 -F s | awk '/^s/ && substr($0,2)+0 > 104857600 {count++} END {print count+0}'
Affiche le nombre de fichiers supprimés >100 Mo.
Intégration Prometheus :
node_filefd_allocated— croissance des fd ouverts.- Comparer df/disk_used vs somme du.
Cron toutes les 5 min : alerte si écart >10 %.
Points clés à retenir
- df montre les blocs alloués depuis le superbloc, du montre les fichiers visibles dans le répertoire.
lsof +L1trouve les processus avec des fichiers (supprimés) par NLINK=0.- Libérer de l'espace :
> /proc/PID/fd/FD— mise à zéro sans redémarrage. - logrotate copytruncate prévient le problème sans HUP.
- Surveillance : scripts avec lsof ou métriques node_exporter.
— Editorial Team
Aucun commentaire pour le moment.