Ist es möglich, einen Symlink zu einer neuen Datei zu "rollen", ohne dass sich dies auf geöffnete Dateihandles auswirkt?

7

Eine Anwendung, die ich lokal entwickle, protokolliert ihre Ausgabe in Dateien, die mit dem aktuellen Zeitstempel formatiert sind, z app-%Y%m%d.log.

Um es einfach zu machen, das aktuelle Tagesprotokoll in einem Terminalfenster zu verfolgen, habe ich einen Symlink mit dem Namen, current.logder auf das heutige Protokoll verweist.

Zu Beginn der Arbeit muss ich jeden Tag den Endprozess beenden, den Symlink auf die heutige Datei verweisen und dann den Befehl erneut ausführen tail -f current.log.

Ist es möglich, das Ziel des Symlinks zu ändern, ohne neu starten zu müssen tail- indem Sie das Ziel des Dateihandles ändern tail, ohne klüger zu sein?

Um diese Aufgabe "Beginn des neuen Arbeitstages" zu automatisieren, wäre es einfach, ein Cron'ed-Skript einzurichten, das den Symlink auf die heutige Datei verweist, aber es scheint, dass der vorhandene tailProzess keine Ahnung hat, dass sich das Ziel geändert hat.

matt b
quelle
Die Betriebssystemabstraktion, die Sie als "Handles" bezeichnen, wird besser als "Dateideskriptoren" bezeichnet. Angesichts des Standes der Microsoft-Dokumentation ist es schwer zu sagen, aber "Deskriptoren" und "Handles" unterscheiden sich wahrscheinlich auf einer bestimmten Ebene.
Bruce Ediger
1
Eine Möglichkeit, dies zu umgehen, besteht darin, sich zusätzlich bei einem Fifo und dann xconsolebeim Fifo anzumelden.
Jodie C

Antworten:

7

Ich denke nicht, dass dies möglich ist, es sei denn, Sie können Tail dazu bringen, die Datei regelmäßig zu schließen und erneut zu öffnen. Ein Schwanz (oder ein anderes Programm) öffnet eine Datei und erhält ein Handle für den Inode dieser Datei. Ab diesem Zeitpunkt werden Dateinamen und Links nicht mehr konsultiert. Aus diesem Grund können Sie eine Datei aus dem Dateisystem löschen, und jedes Programm, in dem diese Datei geöffnet ist, funktioniert weiterhin. Erst wenn das Programm; ast die Datei schließt, wird sie tatsächlich von der Festplatte entfernt.

Update: Zumindest das Versionsende unter OS X verfügt über die Option -F, mit der die Datei erneut geöffnet wird, wenn sie verschoben wurde.

KeithB
quelle
1
Ubuntu hat auch -F (oder --follow = current.log --retry)
charlesbridge
2
tail -Ffunktioniert auch gut in Fedora; Der Hinweis zu OS X gab mir genug Hinweise, um ihn auf meinem System zu überprüfen. Dies ist die beste Antwort, um das zu erreichen, was ich tun möchte (eine Datei weiter verfolgen, auch wenn sie ihren Namen ändert); scheint ziemlich klar zu sein, die Antwort auf meine Grundfrage zu Symlinks ist "nein". Vielen Dank!
Matt B
Schwanz -F funktioniert bei mir in Ubuntu.
Frankadelic
2

Wenn Sie unter einem modernen Linux arbeiten, können Sie inotifywaiteines der Befehlszeilenprogramme aus dem Paket inotify-tools verwenden . Ich habe dies nicht getan, aber es sieht so aus, als inotifywaitkönnte es in einem Shell-Skript verwendet werden, um den Symlink zurückzusetzen und den Symlink anzuhalten und neu tail -fzu starten . Möglicherweise können Sie den Symlink sogar entsorgen und einfach die aktuelle Protokolldatei beenden.

Ohne Verwendung von inotify ist es möglich, ein eigenes schwanzähnliches Programm zu schreiben, das prüft, ob sich die Inode-Nummer des Dateinamens, aus dem es liest, geändert hat. Zu diesem Zeitpunkt kann das Schwanz-ähnliche Programm seinen alten Dateideskriptor schließen und einen neuen Dateideskriptor für den jetzt anderen Dateinamen erhalten. Es ist schwierig, dieses Programm zu schreiben, und es ist anfällig für Rennbedingungen.

Bruce Ediger
quelle
1

Aus Ihrer Beschreibung geht hervor, dass Ihr spezifischer Umstand gelöst werden könnte, indem Sie einen Cron-Job ausführen, der auch den Tail-Prozess beendet / neu gestartet hat. Im Allgemeinen merkt sich Tail (Mac OS ist die Ausnahme), wo Sie sich in der Datei befinden (dh der Byte-Offset). Außerdem zeigt das Handle für geöffnete Dateien auf die Zieldatei und nicht auf den Symlink. Der Symlink wird für den Lesevorgang irrelevant, sobald die Datei geöffnet wurde. Obwohl es möglich ist, Funktionen zu haben, die die Datei basierend auf dem ursprünglichen Pfad erneut öffnen, wenn sich etwas ändert, tun dies die meisten Implementierungen nicht.

Chris Quenelle
quelle
1

Warum melden Sie sich nicht in einer Datei an, current.log, die Sie nach Herzenslust anpassen können, und verwenden Sie dann etwas wie / usr / sbin / logrotate, um diese Datei zu drehen. Sie können in der Konfiguration angeben, dass Sie einige Postrotate-Befehle ausführen möchten, um die alte Datei mit dem angehängten Datum usw. umzubenennen. Dadurch werden keine Symlinks mehr benötigt, und möglicherweise wird auch Ihr Protokollierungscode vereinfacht.

Natürlich ist logrotate möglicherweise nicht auf dem System installiert, für das Sie entwickeln.

gabe.
quelle
1

Sobald ein Programm die Datei geöffnet hat, greift es auch dann auf dieselbe Datei zu, wenn die Datei verschoben oder sogar gelöscht wird. (Wenn Sie eine geöffnete Datei entfernen, wird nur ihr Name entfernt. Die Datei - der Inode - wird tatsächlich gelöscht, sobald sie von keinem Prozess geöffnet wurde.)

Einige Programme beobachten, ob mit der geöffneten Datei etwas passiert. Das klassische Programm tail -fdruckt beispielsweise weiterhin Zeilen, die an dieselbe Datei angehängt sind. Einige moderne Implementierungen (GNU, FreeBSD, NetBSD, OSX) haben tail -Ferkannt, ob eine neue Datei mit demselben Namen an ihren Platz verschoben wurde, und beginnen mit dem Lesen aus der neuen Datei. Multitail kann das auch (ausführen als multitail --retry).

Sie können die Inotify- Schnittstelle unter Linux oder die entsprechende Schnittstelle auf anderen Unices verwenden, um festzustellen, ob sich eine Datei geändert hat. Verwendeninotifywait Sie unter Linux den Befehl .

Gilles 'SO - hör auf böse zu sein'
quelle