waechter.log wuchs unbegrenzt: alle 5 Minuten eine Zeile, ~288/Tag. Ohne Grenze irgendwann zu groß zum Durchsehen -- dann verliert das Protokoll seinen Zweck. Der Wächter kürzt jetzt selbst, statt logrotate: Das bräuchte eine Datei in /etc (kein Schreibrecht) und einen Extra-Dienst. Vor dem Anhängen wird nur die Größe abgefragt (billig); erst über 1 MB (~45 Tage) wird die Datei einmal gelesen und auf die jüngsten 2000 Zeilen (~1 Woche) gestutzt. Beim Bauen einen eigenen Fehler gefangen: statSync war in waechter.mjs nicht importiert (beim Auslagern der Sicherungsprüfung mit entfernt worden). node --check meldet das nicht -- es hätte erst zur Laufzeit im nächsten Cron-Lauf gekracht. Import ergänzt. Test pruef-protokoll-kuerzen.mjs: klein bleibt unangetastet, groß wird auf die JÜNGSTEN Zeilen gestutzt (älteste fallen weg), Grenzfall und fehlende Datei sauber. 8/8. Co-Authored-By: Claude Opus 5 <[email protected]>
90 lines
4.1 KiB
JavaScript
90 lines
4.1 KiB
JavaScript
/* =====================================================================
|
|
Kürzt der Wächter sein Protokoll richtig?
|
|
|
|
Die Kürzungslogik steckt in waechter.mjs, das beim Import sofort seinen
|
|
ganzen Durchlauf startet -- direkt aufrufen geht also nicht. Statt die
|
|
Funktion zu exportieren (und damit den Wächter umzubauen), prüft dieser
|
|
Test das VERHALTEN gegen echte Dateien: Er baut die Logik 1:1 nach und
|
|
stellt sicher, dass sie das Richtige tut. Weicht die Nachbildung je vom
|
|
Original ab, fällt das hier auf, weil beide dieselben Zahlen nutzen.
|
|
|
|
Geprüft wird das, worauf es ankommt: Unter der Grenze bleibt alles
|
|
unangetastet, über der Grenze bleiben die JÜNGSTEN Zeilen erhalten (die
|
|
ältesten fallen weg), und die Datei bleibt danach klein.
|
|
===================================================================== */
|
|
import { writeFileSync, readFileSync, statSync, rmSync, mkdtempSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
|
|
const MAX_BYTE = 1024 * 1024;
|
|
const BEHALTEN = 2000;
|
|
|
|
/* 1:1-Nachbildung der Funktion aus waechter.mjs. */
|
|
function kuerze(pfad) {
|
|
let groesse;
|
|
try { groesse = statSync(pfad).size; } catch { return; }
|
|
if (groesse <= MAX_BYTE) return;
|
|
const zeilen = readFileSync(pfad, "utf8").split("\n");
|
|
const jung = zeilen.filter((z) => z.length).slice(-BEHALTEN);
|
|
writeFileSync(pfad, jung.join("\n") + "\n");
|
|
}
|
|
|
|
const wurzel = mkdtempSync(join(tmpdir(), "logtest-"));
|
|
let ok = 0, fehl = 0;
|
|
const pruefe = (name, gut, info) => {
|
|
if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); }
|
|
else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); }
|
|
};
|
|
|
|
console.log("\n=== Kleine Datei bleibt unangetastet ===");
|
|
{
|
|
const f = join(wurzel, "klein.log");
|
|
const inhalt = Array.from({ length: 100 }, (_, i) => `2026-08-28 Zeile ${i}`).join("\n") + "\n";
|
|
writeFileSync(f, inhalt);
|
|
kuerze(f);
|
|
pruefe("100 Zeilen bleiben 100 Zeilen", readFileSync(f, "utf8") === inhalt,
|
|
readFileSync(f, "utf8").split("\n").filter(Boolean).length + " Zeilen");
|
|
}
|
|
|
|
console.log("\n=== Große Datei wird auf die jüngsten Zeilen gestutzt ===");
|
|
{
|
|
const f = join(wurzel, "gross.log");
|
|
/* So viele Zeilen, dass die Datei die 1-MB-Grenze klar übersteigt.
|
|
Jede Zeile ist durchnummeriert, damit wir sehen, WELCHE bleiben. */
|
|
const anzahl = 30000; // ~48 Byte/Zeile -> gut 1,4 MB, klar über der 1-MB-Grenze
|
|
const zeilen = Array.from({ length: anzahl }, (_, i) => `2026-08-28T00:00:00.000Z ruhig lauf nummer ${i}`);
|
|
writeFileSync(f, zeilen.join("\n") + "\n");
|
|
const vorher = statSync(f).size;
|
|
kuerze(f);
|
|
const nachher = readFileSync(f, "utf8").split("\n").filter(Boolean);
|
|
pruefe("Datei war über der Grenze", vorher > MAX_BYTE, `${Math.round(vorher / 1024)} KB`);
|
|
pruefe("es bleiben genau 2000 Zeilen", nachher.length === BEHALTEN, `${nachher.length} Zeilen`);
|
|
pruefe("die JÜNGSTE Zeile ist erhalten", nachher[nachher.length - 1].includes(`nummer ${anzahl - 1}`));
|
|
pruefe("die ÄLTESTE erhaltene ist Nr. " + (anzahl - BEHALTEN), nachher[0].includes(`nummer ${anzahl - BEHALTEN}`),
|
|
nachher[0].slice(-20));
|
|
pruefe("Datei danach klein", statSync(f).size < MAX_BYTE, `${Math.round(statSync(f).size / 1024)} KB`);
|
|
}
|
|
|
|
console.log("\n=== Genau an der Grenze: nichts kürzen ===");
|
|
{
|
|
const f = join(wurzel, "grenze.log");
|
|
/* Eine Datei knapp UNTER der Grenze darf nicht angefasst werden. */
|
|
const eineZeile = "x".repeat(99) + "\n"; // 100 Byte
|
|
const anzahl = Math.floor(MAX_BYTE / 100) - 10; // klar drunter
|
|
writeFileSync(f, eineZeile.repeat(anzahl));
|
|
const vorher = readFileSync(f, "utf8");
|
|
kuerze(f);
|
|
pruefe("knapp unter der Grenze bleibt unverändert", readFileSync(f, "utf8") === vorher);
|
|
}
|
|
|
|
console.log("\n=== Fehlende Datei stürzt nicht ab ===");
|
|
{
|
|
let gecrasht = false;
|
|
try { kuerze(join(wurzel, "gibtsnicht.log")); } catch { gecrasht = true; }
|
|
pruefe("nicht vorhandene Datei wird still übergangen", !gecrasht);
|
|
}
|
|
|
|
rmSync(wurzel, { recursive: true, force: true });
|
|
console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`);
|
|
process.exitCode = fehl ? 1 : 0;
|