Wie kann ich stdout nach dem Verschieben von logrotate weiter in eine Datei umleiten?

22

Ich habe ein einfaches Skript, das eine Reihe von Protokollen auf dem Bildschirm ausgibt, und ich habe das STDOUT in eine Datei umgeleitet, um die Protokolle zu speichern. Da dieses Skript lange ausgeführt wird, musste ich die Protokolldateien drehen, damit sie in kleinere, besser verwaltbare Dateien umgewandelt werden können.

Das Problem, mit dem ich konfrontiert war, war, dass, sobald die logrotateaktuelle Protokolldatei in eine neue verschoben wird, die neu erstellte Protokolldatei nicht mehr mit den Protokollen gefüllt wird. Es scheint, dass die Dateihandhabung nach dem Entfernen der ursprünglichen Protokolldatei verloren geht und die Umleitung nicht mehr funktioniert.

Ich habe auch diesen Beitrag gefunden, der das gleiche Problem hatte wie ich und behauptet, dass es behoben werden kann, indem man die Ausgabe umleitet , >>anstatt >. Ich habe seine Lösung getestet, aber es hat bei mir nicht funktioniert. Hat jemand eine Idee, wie man die Umleitungsarbeit behält?

Mehran
quelle
4
In Ihrem Fall würde ich weiterhin empfehlen, ">>" anstelle von ">" zu verwenden, wenn Sie in eine abgeschnittene Datei schreiben möchten: Wenn Sie ">>" im Anfügemodus öffnen, wird die Datei bis zum Ende gesucht jedes Mal, wenn es schreibt. Wenn Sie die Datei abschneiden (von XXXX Byte auf 0 Byte), wird sie auf diese Weise "bis zum Ende suchen" und weiß, dass sie jetzt nach Byte 0 schreiben muss. Andernfalls wird möglicherweise nach Byte XXXX und somit geschrieben erstelle eine spärliche Datei mit XXXX null Bytes davor (dh wenn ">", kann sich der FD nur merken, wo er sich in dieser Datei befand, und schreibe von dort aus, ohne zu bemerken, dass die Dateigröße geschrumpft ist!)
Olivier Dulac

Antworten:

25

Sie sollten die copytruncate-Direktive in Ihrer logrotate-Konfiguration für diese Protokolldatei verwenden.

copytruncate Schneidet die ursprüngliche Protokolldatei nach dem Erstellen einer Kopie ab, anstatt die alte Protokolldatei zu verschieben und optional eine neue zu erstellen. Es kann verwendet werden, wenn ein Programm nicht angewiesen werden kann, seine Protokolldatei zu schließen, und daher möglicherweise für immer in die vorherige Protokolldatei schreibt (anhängt). Beachten Sie, dass zwischen dem Kopieren und dem Abschneiden der Datei eine sehr kurze Zeitspanne liegt, sodass möglicherweise einige Protokolldaten verloren gehen. Wenn diese Option verwendet wird, hat die Option create keine Auswirkung, da die alte Protokolldatei an Ort und Stelle bleibt

user9517 unterstützt GoFundMonica
quelle
2
Erwähnenswert: Kurz vor der compressOperation werden die Daten dupliziert. Das hat uns einmal Probleme bereitet, aber das war schlecht, denn wir hätten nicht so nahe am lvPlatzlimit sein sollen. Wie im manSnippet angegeben, gehen möglicherweise einige Protokolldaten zwischen den Kopier- und Kürzungsvorgängen verloren.
Belmin Fernandez
6

Alternativ können Sie auch:

  • Verwenden Sie das Logger-Dienstprogramm in Ihrem Skript anstelle von Piping, und verwenden Sie dafür eine spezielle Funktion (z. B. local5). Beispiel:

    logger -p local5.info -t myscriptname "this is some log data"

  • Konfigurieren Sie syslog so, dass diese Funktion in die gewünschte Protokolldatei geschrieben wird, Beispiel (rsyslog.conf):

    local5.* /var/log/mylogfile

  • Logrotate-Regel für dieses Protokoll einrichten.

tonioc
quelle
Dies funktioniert nur, wenn Sie explizite Ausgabebefehle wie haben echo. Die Ausgabe von Tools von Drittanbietern, die vom Skript aufgerufen werden und auch etwas ausgeben, kann auf diese Weise nicht an den Logger umgeleitet werden
Daniel Alder,
4

Eine andere Alternative zur Iain-Lösung besteht darin, ein postrotateSkript zu verwenden, um Ihr Skript neu zu starten, sobald die Rotation stattgefunden hat. Dies geschieht für viele Daemons (den Daemon neu starten oder neu laden), ohne Ihr Skript zu kennen. Ich weiß nicht, ob diese Lösung für Sie geeignet ist oder nicht (hängt Ihr Skript von einem Zustand ab, der vor einiger Zeit generiert wurde?).

Inhalt von /etc/logrotate.d/your-script-name:

/var/log/your-script-name.log {
    # your current logrotate options
    ...
    postrotate
        # this supposing you have the current pid stored
        cat /run/your-script-name.pid | xargs -r kill
        #relaunch it again
        /usr/local/bin/your-script-name
    endscript
}
Carlos Campderrós
quelle
0

Sie können stdout auf "split" leiten (Teil von coreutils in Linux). Sie können die Datei / stdin nach Größe, Anzahl der Zeilen usw. in Blöcke aufteilen. Sobald Sie einen Block erstellt haben, können Sie ihn bei Bedarf mit logrotate verwalten.

Nazar
quelle