Comment trouver des fichiers volumineux qui ont été supprimés mais qui sont encore ouverts dans une application? Comment peut-on supprimer un tel fichier, même si un processus l'a ouvert?
La situation est que nous exécutons un processus qui remplit un fichier journal à un rythme effarant. Je connais la raison et je peux y remédier. Jusque-là, j'aimerais supprimer ou vider le fichier journal sans arrêter le processus.
Cela ne rm output.log
supprime que les références au fichier, mais celui-ci continue à occuper de l'espace sur le disque jusqu'à la fin du processus. Pire: rm
je n'ai plus aucun moyen de trouver où se trouve le fichier ni quelle est sa taille! Est-il possible 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.
la source
lsof -p <pid>
pour répertorier ses fichiers ouverts et leurs tailles. Le fichier supprimé aura un à(deleted)
côté de lui. Le fichier supprimé sera lié à/proc/<pid>/fd/1
probablement. Je ne sais pas comment faire en sorte qu'un processus arrête d'écrire dans son descripteur de fichier sans le terminer. Je pense que cela dépend du processus.rm
fichiers ed qui sont encore ouverts?lsof | grep "(deleted)"
. Lorsqu'il n'y a plus de processus contenant un fichier supprimé ouvert, le noyau libère les blocs inode et disque. Les processus ne disposent pas de "gestionnaires" grâce auxquels ils peuvent être informés qu'un fichier ouvert, essentiellement verrouillé, a été supprimé du disque.lsof | grep '(deleted)'
fonctionne aussi sous Linux. Sous Linux, vous pouvez être averti de la suppression de fichier (même les fichiers qui ne possèdent déjà aucune entrée dans un répertoire autre que / proc / some-pid / fd) avec le mécanisme inotify (événement IN_DELETE_SELF)somefile
et ouvert dans VIM, puisrm
édité dans un autre processus bash. Je lance alorslsof | grep somefile
et il n'est pas là, même si le fichier est ouvert dans VIM.Réponses:
Si vous ne pouvez pas tuer votre application, vous pouvez tronquer au lieu de supprimer le fichier journal pour récupérer de l'espace. Si le fichier n'était pas ouvert en mode d'ajout (avec
O_APPEND
), il apparaîtra aussi grand qu'avant la prochaine fois que l'application l'écrira (bien que la partie principale soit clairsemée et ressemble à si elle contenait des octets NUL), mais l'espace auront été récupérés (cela ne s'applique pas aux systèmes de fichiers HFS + sur Apple OS / X qui ne prennent pas en charge les fichiers fragmentés).Pour le tronquer:
S'il a déjà été supprimé, sous Linux, vous pouvez toujours le tronquer en procédant comme suit:
Où
$pid
est l'id du processus dans lequel le fichier est ouvert et$fd
un descripteur de fichier sous lequel il est ouvert (avec lequel vous pouvez vérifierlsof -p "$pid"
.Si vous ne connaissez pas le pid et recherchez des fichiers supprimés, vous pouvez effectuer les opérations suivantes:
lsof -nP +L1
, comme mentionné par @ user75021, est une option encore meilleure (plus fiable et plus portable) (liste les fichiers qui ont moins d’un lien).Ou (sous Linux):
Ou trouver les grands avec
zsh
:Une autre solution, si l’application est liée dynamiquement, consiste à lui associer un débogueur et à lui faire appeler
close(fd)
suivi d’un nouveauopen("the-file", ....)
.la source
truncate
commande qui fait la même chose de manière plus explicite.lsof
sera probablement la solution la plus proche d'une solution portable que vous pouvez obtenir pour lister les fichiers ouverts. l’approche du débogueur pour fermer le fd sous les pieds d’application devrait également être assez portable.df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud
(et ensuite, d'envoyer facilement des signaux aux contrevenants pour les forcer à libérer le fd)lsof +L1
. Dans la page de manuel lsof: "Une spécification du formulaire+L1
sélectionnera les fichiers ouverts non liés. Une spécification du formulaire+aL1 <file_system>
sélectionnera les fichiers ouverts non liés sur le système de fichiers spécifié.". Cela devrait être un peu plus fiable que grepping.Découvrez le quickstart ici:
lsof
QuickstartJe suis surpris que personne n'ait mentionné le fichier de démarrage rapide lsof (inclus avec lsof). La section "3.a" montre comment trouver des fichiers ouverts et non liés:
Par exemple:
Sur les systèmes Red Hat pour rechercher la copie locale du fichier de démarrage rapide, je procède généralement comme suit:
... ou ca:
la source
Il appartient au pilote du système de fichiers de libérer l’espace alloué, ce qui ne se produit généralement que lorsque tous les descripteurs de fichier faisant référence à ce fichier sont publiés. Donc, vous ne pouvez pas vraiment récupérer l'espace, sauf si vous fermez le fichier par l'application. Ce qui signifie soit le terminer soit jouer avec "un peu" dans un débogueur (par exemple fermer le fichier et s'assurer qu'il n'est pas ouvert / écrit de nouveau, ou ouvrir à la
/dev/null
place). Ou vous pourriez pirater le noyau, mais je déconseillerais cela.Tronquer le fichier comme suggéré par Stephane peut aider, mais le résultat réel dépendra également de votre système de fichiers (par exemple, les blocs pré-alloués ne seront probablement libérés qu'après la fermeture du fichier).
La raison derrière ce comportement est que le noyau ne sait pas quoi faire avec les demandes de données (en lecture et en écriture, mais la lecture est en réalité plus critique) en ciblant un tel fichier.
la source
fallocate
sous Linux 4.9. Pouvez-vous clarifier sous quel système de fichiers et dans quelle condition tronquer un fichier ne récupère pas de l'espace?