Comment retrouver des fichiers volumineux supprimés mais toujours ouverts dans une application ? Comment supprimer un tel fichier alors qu'un processus l'a ouvert ?
La situation est que nous exécutons un processus qui remplit un fichier journal à un rythme effréné. Je connais la raison et je peux y remédier. Jusque-là, je voudrais rm ou vider le fichier journal sans arrêter le processus.
Faire simplement rm output.log
supprime uniquement les références au fichier, mais il continue d'occuper de l'espace sur le disque jusqu'à ce que le processus soit terminé. Pire :après rm
Je n'ai plus aucun moyen de trouver où se trouve le fichier ni quelle est sa taille ! Existe-t-il un moyen de trouver le fichier, et éventuellement de le vider, même s'il est toujours ouvert dans un autre processus ?
Je fais spécifiquement référence aux systèmes d'exploitation basés sur Linux tels que Debian ou RHEL.
Réponse acceptée :
Si vous ne pouvez pas tuer votre application, vous pouvez tronquer au lieu de supprimer le fichier journal pour récupérer l'espace. Si le fichier n'a pas été ouvert en mode ajout (avec O_APPEND
), alors le fichier apparaîtra aussi grand qu'avant la prochaine fois que l'application y écrira (bien qu'avec la partie principale clairsemée et semblant contenir des octets NUL), mais l'espace aura été récupéré (cela ne s'applique pas à HFS+ systèmes de fichiers sur Apple OS/X qui ne prennent pas en charge les fichiers fragmentés).
Pour le tronquer :
: > /path/to/the/file.log
S'il a déjà été supprimé, sous Linux, vous pouvez toujours le tronquer en faisant :
: > "/proc/$pid/fd/$fd"
Où $pid
est l'ID de processus du processus qui a ouvert le fichier, et $fd
un descripteur de fichier sous lequel il est ouvert (que vous pouvez vérifier avec lsof -p "$pid"
.
Si vous ne connaissez pas le pid et recherchez des fichiers supprimés, vous pouvez faire :
lsof -nP | grep '(deleted)'
lsof -nP +L1
, comme mentionné par @user75021 est une option encore meilleure (plus fiable et plus portable) (liste des fichiers qui ont moins d'un lien).
Ou (sous Linux) :
find /proc/*/fd -ls | grep '(deleted)'
Ou pour trouver les grands avec zsh
:
ls -ld /proc/*/fd/*(-.LM+1l0)
Une alternative, si l'application est liée dynamiquement, est de lui attacher un débogueur et de lui faire appeler close(fd)
suivi d'un nouveau open("the-file", ....)
.