Comment un programme de journalisation peut-il continuer à se connecter à un fichier supprimé?


12

Dans la section Unix Power Tools, 3e édition : au lieu de supprimer un fichier, videz -le:

Si un processus actif a le fichier ouvert (pas rare pour les fichiers journaux), la suppression du fichier et la création d'un nouveau n'affecteront pas le programme de journalisation; ces messages continueront simplement vers le fichier qui n'est plus lié . Vider le fichier ne rompt pas l'association et efface donc le fichier sans affecter le programme de journalisation.

(c'est moi qui souligne )

Je ne comprends pas pourquoi un programme continuera à se connecter à un fichier supprimé. Est-ce parce que l'entrée du descripteur de fichier n'est pas supprimée de la table de processus?

Réponses:


11

Lorsque vous supprimez un fichier, vous supprimez vraiment un lien vers le fichier (vers l'inode). Si quelqu'un a déjà ouvert ce fichier, il peut conserver le descripteur de fichier dont il dispose. Le fichier reste sur le disque, occupe de l'espace et peut être écrit et lu si vous y avez accès.

La unlinkfonction est définie avec ce comportement par POSIX:

Lorsque le nombre de liens du fichier devient 0 et qu'aucun processus n'a ouvert le fichier, l'espace occupé par le fichier doit être libéré et le fichier n'est plus accessible. Si un ou plusieurs processus ont le fichier ouvert lorsque le dernier lien est supprimé, le lien doit être supprimé avant le retour de unlink (), mais la suppression du contenu du fichier doit être différée jusqu'à ce que toutes les références au fichier soient fermées .

Ce conseil à cause de ce comportement. Le démon aura le fichier ouvert et ne remarquera pas qu'il a été supprimé (sauf s'il le surveillait spécifiquement, ce qui est rare). Il continuera à écrire allègrement dans le descripteur de fichier existant qu'il possède: vous continuerez à prendre (plus) d'espace sur le disque, mais vous ne pourrez voir aucun des messages qu'il écrit, donc vous êtes vraiment dans le pire des deux mondes. Si vous tronquez le fichier à une longueur nulle à la place, l'espace est libéré immédiatement et tous les nouveaux messages seront ajoutés à la nouvelle fin du fichier où vous pourrez les voir.

Finalement, lorsque le démon se termine ou closes le fichier , l'espace sera libéré. Personne de nouveau ne peut ouvrir le fichier entre-temps (sauf via des interfaces réfléchissantes spécifiques au système comme Linux/proc/x/fd/... ). Il est également garanti que:

Si le nombre de liens du fichier est de 0, lorsque tous les descripteurs de fichiers associés au fichier sont fermés, l'espace occupé par le fichier doit être libéré et le fichier ne doit plus être accessible.

Vous ne perdez donc pas votre espace disque de façon permanente, mais vous ne gagnez rien en supprimant le fichier et vous perdez l'accès aux nouveaux messages.


1
Que se passera-t-il si un utilisateur (disons root ici) tente de se dissocier /proc/x/fd/y? Cela entraînerait-il l'échec du processus d'écriture dans le descripteur de fichier, ou s'agit-il d'une opération illégale?
nanofarad

@hexafraction /proc/*/fd/*sont des liens symboliques vers de vrais fichiers, donc les supprimer ne supprimera pas le fichier. Je vous suggère d'expérimenter :) (pas sur le système de production bien sûr!)
Ruslan

1
@MichaelHomer Peut-être pourriez-vous préciser dans votre réponse qu'une fois qu'un fichier est dissocié, le processus ayant un descripteur de fichier pointant vers lui peut le lier à nouveau, sur le même chemin ou non. Cela peut parfois être utile.
lgeorget

@hexafraction Eh bien, ce ne sont que des représentations (dans l'espace du système de fichiers) de l'état du processus et des objets. Si vous supprimez ces représentations dans l'espace du système de fichiers, rien ne devrait arriver au processus réel - à moins qu'il (ou un autre processus) ne repose sur cette représentation. Pas sûr que vous puissiez utiliser de façon rmincontinente à l'intérieur /procou /syssans être averti par le système de toute façon.
David Tonhofer

@lgeorget Comment cela est-il accompli?
Michael

8

Exactement.

Les fichiers sont tripartites.

  • Le contenu, c'est-à-dire un tableau plat d'octets, écrit quelque part sur un disque ou généré à la volée.
  • Le nœud d'index , ou inode pour faire court, qui est une structure de données remplie et utilisée par le noyau. Il contient toutes les métadonnées (taille, autorisation, etc.) concernant le fichier et indique également l'emplacement du contenu du fichier.
  • Une ou plusieurs entrées de répertoire , qui sont des emplacements, manipulées comme des chemins comme /home/user/personal_file, qui agissent comme des poignées à travers lequel vous pouvez utiliser le fichier, modifier son contenu, modifier ses métadonnées, etc.

Lorsque vous ouvrez un fichier, vous donnez le chemin d'accès au système d'exploitation et il vous renvoie un handle directement vers l'inode. Avec cette poignée, appelée descripteur de fichier, vous pouvez manipuler le fichier comme vous le souhaitez (ou au moins, comme le permet le système d'exploitation).

Vous ne pouvez jamais supprimer directement un inode, vous devez donner un chemin vers le système d'exploitation pour exiger la suppression. Ainsi, lorsque vous souhaitez supprimer un fichier, vous supprimez uniquement l'entrée de répertoire. Si le fichier a d'autres entrées de répertoire, il continuera à être accessible, et même s'il ne l'a pas, son inode ne sera pas supprimé tant qu'il y aura encore des descripteurs de fichier pointant vers lui. @ La réponse de MichaelHomer est plus technique et plus détaillée sur ce sujet spécifique.


4

Les 2 autres réponses expliquent bien le problème - un fichier n'est pas "supprimé" jusqu'à ce que tous les liens du répertoire vers lui et tous les descripteurs de fichiers ouverts soient partis.

Pour éviter cela, c'est une bonne habitude à utiliser

> /var/log/bigfile

au lieu de

rm -f /var/log/bigfile

car cela réinitialise simplement le contenu à 0 octet au lieu de le supprimer, et vous pouvez toujours voir ce qui y est écrit.

Si vous avez supprimé le fichier et que vous êtes sous Linux où vous avez un système de fichiers / proc / fd, vous pouvez toujours utiliser

> /proc/12345/fd/3

pour mettre à zéro le contenu du fichier (en supposant que 12345 est votre identifiant de processus et 3 est le numéro fd du gros fichier). Cela peut vous sauver la vie si votre disque est plein et que vous ne pouvez pas tuer le processus qui écrit votre fichier journal pour une raison quelconque.


> /var/log/bigfilesupprime les données existantes dans le fichier mais n'empêche pas les programmes d'y écrire. Il y a très peu de circonstances où c'est la bonne chose. Je dirais que c'est une mauvaise habitude. Si vous souhaitez supprimer un fichier, utilisez rm. Si vous souhaitez arrêter les programmes qui y écrivent, tuez-les ou faites-les arrêter de toute façon, avant ou après la suppression.
Gilles 'SO- arrête d'être méchant'

1
@Giles, cette rubrique concerne le fait que la suppression n'aidera pas si un programme a toujours le fichier ouvert. Et si votre disque est plein parce que certains programmes se comportent mal et se syslogdremplissent /var/log/messages,> /var/log/messages c'est une bien meilleure option que de tuer syslogd. Bien sûr, cela ne devrait pas vous empêcher d'analyser le problème en premier lieu.
Guntram Blohm prend en charge Monica le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.