Layer 8Ehrlicher Tech-Support
BetriebssystemSchweregrad: Lästig

logrotate: Alte Logdatei wächst weiter, die neue bleibt leer

Nach der Rotation schreibt das Programm in die umbenannte Datei weiter, weil es den Dateigriff behält. copytruncate oder postrotate sind die Antwort.

Aufwand:
ca. 20 Min.
Voraussetzung:
Root-Rechte oder sudo auf dem betroffenen System, Zugriff auf /etc/logrotate.d/ und die Konfiguration des schreibenden Programms, lsof oder ls -l /proc/<pid>/fd, um offene Dateigriffe zu sehen
Gilt für:
logrotate laut Handbuchseite logrotate(8) auf man7.org, abgerufen am 17.10.2026

Das Symptom

Die Festplatte eines Servers läuft voll. Im Logverzeichnis liegt die erwartete Ordnung: app.log, app.log.1, app.log.2.gz und so weiter, die Rotation läuft täglich. Nur stimmt etwas nicht. app.log hat null Byte und ist seit Tagen null Byte. app.log.1 dagegen hat vierzig Gigabyte und wächst im Sekundentakt. Jeden Morgen benennt logrotate die Riesendatei um, legt eine leere neue an, und die Riesendatei wächst unter neuem Namen weiter. Komprimiert wird sie nie, denn sie ist ja gerade erst rotiert worden.

Der erste Verdacht trifft logrotate. Der zweite das Dateisystem. Beide sind unschuldig.

Die „Layer 8“-Wahrheit

Ein Programm, das eine Logdatei geöffnet hat, hält keinen Dateinamen, sondern einen Dateigriff auf die Datei selbst. Wird die Datei umbenannt, zeigt der Griff weiter auf dieselbe Datei, jetzt unter dem Namen mit .1. Die neue Datei, die logrotate per create anlegt, hat niemand geöffnet; sie bleibt leer. Das Programm schreibt treu dorthin, wo es immer geschrieben hat, und niemand hat ihm gesagt, dass sich etwas geändert hat.

Die Handbuchseite von logrotate kennt diesen Fall und beschreibt ihn bei der Option, die dafür gebaut wurde. copytruncate ist einsetzbar, „when some program cannot be told to close its logfile and thus might continue writing (appending) to the previous log file forever.“ Die Option ändert das Verfahren: „Truncate the original log file to zero size in place after creating a copy, instead of moving the old log file and optionally creating a new one.“ Die Datei bleibt also, wo sie ist, der Griff des Programms bleibt gültig, und das Programm schreibt in eine geleerte Datei weiter. Zwei Nebenwirkungen nennt die Seite gleich mit: create ist dann wirkungslos, weil die alte Datei an Ort und Stelle bleibt, und zwischen Kopieren und Leeren liegt ein kleines Zeitfenster, in dem Zeilen verloren gehen können.

Deshalb ist copytruncate die zweitbeste Lösung. Die beste ist, dem Programm das Neuöffnen mitzuteilen. Die meisten Dienste, die Logdateien schreiben, haben dafür ein Signal oder einen Reload-Befehl; welches, steht in ihrer Dokumentation, nicht in der von logrotate. Dieser Befehl gehört in den postrotate-Abschnitt. Dann wird die alte Datei umbenannt, die neue angelegt, der Dienst öffnet neu, und nichts fehlt.

Ein Detail macht beide Wege robust: delaycompress. Die Handbuchseite beschreibt sie als Verschieben der Kompression der vorherigen Logdatei auf den nächsten Rotationszyklus, wirksam nur zusammen mit compress, und nennt als Einsatzfall wieder das Programm, das nicht zum Schließen seiner Logdatei gebracht werden kann und deshalb noch eine Weile in die vorherige Datei schreibt. Komprimiert wird damit immer erst die Datei, in die garantiert niemand mehr schreibt.

Der Fehler lag von Anfang an nicht in der Rotation, sondern in der Annahme, ein umbenannter Name würde ein laufendes Programm interessieren. Tut er nicht. Das Programm hat die Datei; der Name ist nur das, was Menschen sehen.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Prüfen, wer die alte Datei noch offen hält

    Wächst die Datei mit der Endung .1 weiter, während die neue bei null Byte bleibt, hält ein Prozess einen Dateigriff auf die umbenannte Datei. lsof zeigt den Prozess und die Datei; alternativ listet /proc/<pid>/fd die offenen Dateien eines bekannten Prozesses. Das Ergebnis entscheidet über den Weg: Kann dieses Programm per Signal oder Befehl zum Neuöffnen seiner Logdatei gebracht werden, ist ein postrotate-Skript die saubere Lösung. Kann es das nicht, bleibt copytruncate.

    sudo lsof +L1 | grep -E '\.log(\.[0-9]+)?'
    sudo ls -l /proc/<pid>/fd | grep log
    
  2. 2.

    Für Programme mit Neuöffnen-Signal: postrotate statt copytruncate

    Viele Dienste öffnen ihre Logdatei neu, wenn sie ein bestimmtes Signal oder einen Reload-Befehl bekommen; welches, steht in der Dokumentation des jeweiligen Dienstes und wird hier nicht geraten. Dieser Befehl gehört in den postrotate-Abschnitt der logrotate-Konfiguration, der laut Handbuchseite nach dem Anlegen der neuen Datei per create läuft. So schreibt der Dienst nach der Rotation in die neue Datei, und die alte ist vollständig, ohne das Zeitfenster von copytruncate.

    /var/log/beispiel/*.log {
        daily
        rotate 14
        compress
        delaycompress
        missingok
        notifempty
        create 0640 beispiel adm
        postrotate
            # Befehl aus der Dokumentation des Dienstes, der die Logdatei neu öffnet
        endscript
    }
    
  3. 3.

    Für Programme ohne Neuöffnen: copytruncate setzen und create streichen

    Wenn das Programm nicht zum Neuöffnen gebracht werden kann, bleibt copytruncate: Die Datei wird kopiert und an Ort und Stelle auf null gekürzt, der Dateigriff des Programms bleibt gültig. Die Handbuchseite stellt klar, dass create dann wirkungslos ist, weil die alte Datei an Ort und Stelle bleibt; die Zeile kann weg, damit die Konfiguration nicht etwas verspricht, was sie nicht tut. Den möglichen Verlust weniger Zeilen zwischen Kopieren und Kürzen nimmt man damit bewusst in Kauf.

    /var/log/beispiel/*.log {
        daily
        rotate 14
        compress
        delaycompress
        missingok
        notifempty
        copytruncate
    }
    
  4. 4.

    Die Konfiguration im Probelauf und dann erzwungen testen

    logrotate -d führt die Konfiguration im Debug-Modus aus und zeigt, was geschehen würde, ohne etwas zu verändern. logrotate -f erzwingt eine Rotation, auch wenn sie nach Zeitplan noch nicht fällig wäre, und eignet sich, um danach zu prüfen, ob die neue Datei wächst und die alte stillsteht. Wer beides mit der konkreten Datei aus /etc/logrotate.d aufruft, testet nur diese Regel und nicht die gesamte Systemkonfiguration mit.

    sudo logrotate -d /etc/logrotate.d/beispiel
    sudo logrotate -f /etc/logrotate.d/beispiel
    ls -l /var/log/beispiel/
    

Häufige Fragen (FAQ)

?Warum schreibt das Programm nach der Rotation in die alte Datei weiter?

Weil logrotate im Normalfall die Datei umbenennt und das Programm nicht den Namen, sondern einen offenen Dateigriff hält. Der zeigt nach dem Umbenennen weiter auf dieselbe Datei, die jetzt .1 heißt. Die Handbuchseite beschreibt genau diesen Fall bei der Option copytruncate: Sie sei einsetzbar, „when some program cannot be told to close its logfile and thus might continue writing (appending) to the previous log file forever.“ Die mit create neu angelegte Datei bleibt leer, weil niemand sie geöffnet hat. Der Fehler liegt also nicht an logrotate, sondern daran, dass dem Programm nicht gesagt wurde, dass sich etwas geändert hat.

?Was tut copytruncate anders als die normale Rotation?

Es lässt die Datei an Ort und Stelle und leert sie, statt sie wegzubewegen. Die Handbuchseite: „Truncate the original log file to zero size in place after creating a copy, instead of moving the old log file and optionally creating a new one.“ Das Programm schreibt mit seinem alten Dateigriff weiter, nur eben in eine jetzt leere Datei. Die Seite nennt zwei Folgen: „When this option is used, the create option will have no effect, as the old log file stays in place.“ Und die Option impliziert laut Handbuchseite norenamecopy. Wer copytruncate und create zusammen in einer Konfiguration sieht, weiß, dass eins davon nichts tut.

?Gehen mit copytruncate Zeilen verloren?

Möglicherweise ja, und die Handbuchseite verschweigt das nicht: „Note that there is a very small time slice between copying the file and truncating it, so some logging data might be lost.“ Zwischen dem Kopieren und dem Leeren kann das Programm Zeilen schreiben, die dann weder in der Kopie noch in der geleerten Datei stehen. Für ein Zugriffsprotokoll mit tausend Zeilen pro Sekunde ist das ein echter Verlust, für ein Fehlerprotokoll mit zehn Zeilen am Tag ein theoretischer. Die verlustfreie Lösung ist die normale Rotation mit einem postrotate-Skript, das dem Programm das Neuöffnen seiner Logdatei mitteilt, sofern das Programm das kann.

?Wozu delaycompress, wenn ich schon ein postrotate-Skript habe?

Weil das Programm zwischen Umbenennen und Signal noch in die alte Datei schreibt und eine Datei, die gerade komprimiert wird, dafür ungeeignet ist. Die Handbuchseite beschreibt delaycompress so: „Postpone compression of the previous log file to the next rotation cycle. This only has effect when used in combination with compress.“ Und weiter, die Option sei einsetzbar, wenn ein Programm nicht angewiesen werden kann, seine Logdatei zu schließen, und deshalb noch eine Weile in die vorherige Datei schreibt. Die Kombination aus compress und delaycompress komprimiert also immer erst die vorletzte Datei, wenn sicher niemand mehr hineinschreibt.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

OSLästigArgument list too long

bash: Argument list too long

Der Befehl bricht mit 'Argument list too long' ab, weil ein * zu viele Dateien liefert. So löst du es mit find und xargs statt Globbing.

OSLästigUNPROTECTED PRIVATE KEY FILE

SSH: Permissions for key are too open

SSH verweigert den Schlüssel, weil die Rechte zu offen seien? Ein privater Schlüssel darf nur dir gehören — mit einem chmod ist es in Sekunden behoben.