Wie kann ein Protokollprogramm weiterhin in einer gelöschten Datei protokollieren?

12

Aus den Unix-Elektrowerkzeugen, 3. Ausgabe : Anstatt eine Datei zu entfernen, leeren Sie den Abschnitt:

Wenn bei einem aktiven Prozess die Datei geöffnet ist (was bei Protokolldateien nicht ungewöhnlich ist), wirkt sich das Entfernen der Datei und das Erstellen einer neuen Datei nicht auf das Protokollierungsprogramm aus. Diese Nachrichten werden einfach weiter in die Datei geleitet, die nicht mehr verknüpft ist . Durch das Leeren der Datei wird die Zuordnung nicht unterbrochen, sodass die Datei gelöscht wird, ohne dass dies Auswirkungen auf das Protokollierungsprogramm hat.

( Hervorhebung von mir )

Ich verstehe nicht, warum ein Programm weiterhin in einer gelöschten Datei protokolliert. Liegt es daran, dass der Dateideskriptoreintrag nicht aus der Prozesstabelle entfernt wird?

Geek
quelle

Antworten:

11

Wenn Sie eine Datei löschen, entfernen Sie wirklich einen Link zur Datei (zum Inode). Wenn jemand diese Datei bereits geöffnet hat, kann er den Dateideskriptor behalten, den er hat. Die Datei verbleibt auf der Festplatte, nimmt Speicherplatz ein und kann beschrieben und gelesen werden, wenn Sie Zugriff darauf haben.

Die unlinkFunktion wird mit diesem Verhalten von POSIX definiert:

Wenn die Anzahl der Verknüpfungen der Datei 0 wird und kein Prozess die Datei geöffnet hat, wird der von der Datei belegte Speicherplatz freigegeben und die Datei ist nicht mehr zugänglich. Wenn bei einem oder mehreren Prozessen die Datei geöffnet ist, wenn der letzte Link entfernt wird, wird der Link entfernt, bevor unlink () zurückgegeben wird. Das Entfernen des Dateiinhalts wird jedoch verschoben, bis alle Verweise auf die Datei geschlossen sind .

Dieser Ratschlag wegen dieses Verhaltens. Der Dämon hat die Datei geöffnet und bemerkt nicht, dass sie gelöscht wurde (es sei denn, er hat sie speziell überwacht, was ungewöhnlich ist). Es wird weiterhin munter in den vorhandenen Dateideskriptor geschrieben, den es hat: Sie werden weiterhin (mehr) Speicherplatz auf der Festplatte belegen, aber Sie werden keine der Nachrichten sehen können, die es schreibt, also sind Sie wirklich im schlimmsten Fall beider Welten. Wenn Sie die Datei stattdessen auf die Länge Null kürzen, wird der Speicherplatz sofort freigegeben, und alle neuen Nachrichten werden am neuen Ende der Datei angehängt, wo Sie sie sehen können.

Wenn der Dämon closedie Datei beendet oder beendet , wird der Speicherplatz freigegeben. In der Zwischenzeit kann niemand Neues die Datei öffnen (außer über systemspezifische reflektierende Schnittstellen wie Linux/proc/x/fd/... ). Es ist auch garantiert, dass:

Wenn die Verknüpfungsanzahl der Datei 0 ist und alle mit der Datei verknüpften Dateideskriptoren geschlossen sind, wird der von der Datei belegte Speicherplatz freigegeben und die Datei ist nicht mehr zugänglich.

Sie verlieren also nicht dauerhaft Speicherplatz, aber durch das Löschen der Datei erhalten Sie nichts und verlieren den Zugriff auf neue Nachrichten.

Michael Homer
quelle
1
Was passiert, wenn ein Benutzer (sagen wir hier root) versucht, die Verknüpfung aufzuheben /proc/x/fd/y? Würde dies dazu führen, dass der Prozess nicht in den Dateideskriptor schreibt, oder handelt es sich um eine unzulässige Operation?
Stellen Sie Monica wieder her - ζ--
@hexafraction /proc/*/fd/*sind Symlinks zu echten Dateien. Wenn Sie sie entfernen, wird die Datei nicht gelöscht. Ich würde vorschlagen, dass Sie experimentieren :) (natürlich nicht im Produktionssystem!)
Ruslan
1
@MichaelHomer Vielleicht könnten Sie in Ihrer Antwort klarstellen, dass der Prozess, auf den ein Dateideskriptor verweist, nach dem Aufheben der Verknüpfung einer Datei erneut verknüpft werden kann, auf demselben Pfad oder nicht. Dies kann manchmal nützlich sein.
Lgeorget
@hexafraction Nun, dies sind nur Darstellungen (im Dateisystembereich) des Prozessstatus und der Objekte. Wenn Sie diese Darstellungen im Dateisystembereich entfernen, sollte dem eigentlichen Prozess nichts passieren - es sei denn, er (oder ein anderer Prozess) setzt voraus, dass diese Darstellung vorhanden ist. Ich bin mir nicht sicher, ob Sie es im rmInneren /procoder /sysohne Hinweis des Systems verwenden können.
David Tonhofer
@lgeorget Wie wird das erreicht?
Michael
8

Genau.

Dateien sind dreiteilig.

  • Der Inhalt, dh ein flaches Array von Bytes, das irgendwo auf eine Festplatte geschrieben oder im laufenden Betrieb generiert wird.
  • Der Indexknoten , kurz Inode , eine Datenstruktur, die vom Kernel ausgefüllt und verwendet wird. Es enthält alle Metadaten (Größe, Berechtigung usw.) der Datei sowie Zeiger auf den Speicherort des Inhalts der Datei.
  • Ein oder mehrere Verzeichniseinträge , die Standorte sind, manipuliert als Pfade wie /home/user/personal_file, die als Griffe dienen , über die Sie die Datei verwenden kann, seinen Inhalt ändern, seine Metadaten ändern usw.

Wenn Sie eine Datei öffnen, geben Sie den Pfad zum Betriebssystem an und erhalten ein Handle direkt zum Inode. Mit diesem Handle, das als Dateideskriptor bezeichnet wird, können Sie die Datei beliebig bearbeiten (oder zumindest, wie vom Betriebssystem zugelassen).

Sie können einen Inode niemals direkt löschen. Sie müssen einen Pfad zum Betriebssystem angeben, um das Löschen zu erfordern. Wenn Sie also eine Datei löschen möchten, löschen Sie nur den Verzeichniseintrag. Wenn die Datei andere Verzeichniseinträge enthält, ist weiterhin auf sie zugegriffen, und selbst wenn dies nicht der Fall ist, wird ihr Inode nicht gelöscht, solange noch Dateideskriptoren darauf verweisen. @ MichaelHomers Antwort ist technischer und detaillierter zu diesem speziellen Thema.

lgeorget
quelle
4

Die anderen beiden Antworten erklären das Problem gut - eine Datei wird erst "gelöscht", wenn alle Verzeichnisverknüpfungen und alle geöffneten Dateideskriptoren verschwunden sind.

Um dies zu vermeiden, ist es eine gute Angewohnheit zu verwenden

> /var/log/bigfile

Anstatt von

rm -f /var/log/bigfile

da dies den Inhalt nur auf 0 Bytes zurücksetzt, anstatt ihn zu löschen, und Sie immer noch sehen können, was darauf geschrieben ist.

Wenn Sie die Datei gelöscht haben und sich unter Linux befinden, auf dem Sie ein / proc / fd-Dateisystem haben, können Sie diese weiterhin verwenden

> /proc/12345/fd/3

um den Inhalt der Datei auf Null zu setzen (vorausgesetzt, 12345 ist Ihre Prozess-ID und 3 ist die fd-Nummer der großen Datei). Dies kann lebensrettend sein, wenn Ihre Festplatte voll ist und Sie den Prozess, der Ihre Protokolldatei schreibt, aus irgendeinem Grund nicht beenden können.

Guntram Blohm unterstützt Monica
quelle
> /var/log/bigfileEntfernt die vorhandenen Daten in der Datei, verhindert jedoch nicht, dass Programme dort schreiben. Es gibt nur sehr wenige Umstände, unter denen es das Richtige ist. Ich würde sagen, es ist eine schlechte Angewohnheit, sich darauf einzulassen. Wenn Sie eine Datei löschen möchten, verwenden Sie rm. Wenn Sie Programme stoppen möchten, die dort schreiben, beenden Sie sie oder lassen Sie sie auf andere Weise vor oder nach dem Löschen aufhören zu schreiben.
Gilles 'SO - hör auf böse zu sein'
1
@Giles, in diesem Thema geht es um die Tatsache, dass das Löschen nicht hilft, wenn in einem Programm die Datei noch geöffnet ist. Und wenn Ihre Festplatte voll ist, weil sich ein Programm schlecht verhält und syslogdfüllt /var/log/messages, > /var/log/messagesist dies eine viel bessere Option als das Beenden syslogd. Das sollte Sie natürlich nicht davon abhalten, das Problem überhaupt zu analysieren.
Guntram Blohm unterstützt Monica