diskdelta: welche Verzeichnisse auf der Platte gewachsen sind

Ein kleines Werkzeug, das bei jedem Lauf Verzeichnisgrößen aufzeichnet und das Wachstum seit dem letzten Lauf und seit einer Woche ausgibt, mit optionalem Alarm bei wenig freiem Platz.

Das Problem

Läuft auf einem kleinen Server die Platte voll, ist die erste Frage, was gewachsen ist. du und ncdu zeigen, was jetzt groß ist. Was sich seit gestern oder seit letzter Woche verändert hat, zeigen sie nicht. Läuft eine Platte immer wieder voll, muss man das gewachsene Verzeichnis also jedes Mal von Hand suchen.

Wie es funktioniert

Jeder Lauf von diskdelta zeichnet die Größe jedes Verzeichnisses bis zu einer gewählten Tiefe unterhalb eines Wurzelverzeichnisses auf (Standard: 3 Ebenen) und speichert diesen Snapshot als JSON-Datei in ~/.local/state/diskdelta. Die letzten 30 Snapshots bleiben erhalten. Danach vergleicht es den neuen Snapshot mit dem vorherigen und mit dem neuesten Snapshot, der mindestens sieben Tage alt ist, und gibt beide Wachstumstabellen sowie die größten Verzeichnisse aus.

Die Größen werden so gemessen, wie du sie meldet: belegte Blöcke, Hardlinks nur einmal gezählt. Symlinks werden nicht verfolgt, und der Scan bleibt auf dem Dateisystem des Wurzelverzeichnisses.

Wachsen in /tmp/render-cache 2 GB hinzu, wachsen auch /tmp und / um 2 GB. Damit dieselbe Änderung nicht dreimal erscheint, lässt die Wachstumstabelle ein Verzeichnis weg, wenn eines seiner aufgezeichneten Unterverzeichnisse mindestens 90 Prozent seiner Änderung erklärt. Die Tabelle nennt dann das tiefste Verzeichnis, das das Wachstum erklärt. Verteilt sich die Änderung auf mehrere Unterverzeichnisse, bleibt das Elternverzeichnis in der Tabelle.

Mit --min-free 2G gibt es ALERT aus und endet mit Status 2, wenn weniger als 2 GB frei sind. Ein Skript oder Cron-Job kann also auf den Exit-Status reagieren. Das README schlägt einen täglichen Cron-Eintrag vor:

30 4 * * * timeout 900 diskdelta / --depth 3 --min-free 2G >> ~/diskdelta.log 2>&1

Das ist das Beispiel aus dem README (die Pfade sind dort als Beispielpfade gekennzeichnet):

$ diskdelta / --depth 3 --min-free 2G
2026-10-25 04:30  /  free 3.1G

Growth since last run (2026-10-24 04:30, free then 5.6G, change -2.5G):
      2.1G  /tmp/render-cache
    290.4M  /home/dev/.cache/uv
     61.0M  /var/log/journal

Growth since 7 days (2026-10-18 04:30, free then 8.4G, change -5.3G):
      2.1G  /tmp/render-cache
      1.9G  /home/dev/.local/share/claude/versions
    ...

Largest directories:
     14.2G  /home
      ...

Das Werkzeug braucht Python 3.10 oder neuer und hat keine Abhängigkeiten.

Tests

Die Scan-Tests schreiben Dateien bekannter Größe in ein temporäres Verzeichnis und prüfen, welche Verzeichnisse bei einer gegebenen Tiefe aufgezeichnet werden und dass Elternverzeichnisse mindestens so groß sind wie ihre Kinder. Ein Test legt einen Hardlink und einen Symlink zurück auf die Wurzel an. Der Hardlink darf nur einmal zählen, und die Schleife darf nicht verfolgt werden.

Die Wachstumstests arbeiten mit Größentabellen. Sie prüfen, dass die Änderung dem tiefsten Verzeichnis zugeordnet wird, dass ein Elternverzeichnis verschwindet, wenn ein einzelnes Kind sein Wachstum erklärt, dass es bleibt, wenn sich zwei Kinder die Änderung teilen, und dass neue und schrumpfende Verzeichnisse richtig behandelt werden. Weitere Tests decken die Wahl des Sieben-Tage-Vergleichs, das Einlesen von Größen (2G, 500M, 1.5GiB) und die lesbare Ausgabe ab.

Der Kommandozeilentest ruft das Werkzeug dreimal auf einem temporären Verzeichnis auf: Der erste Lauf meldet "no snapshot yet", der zweite listet ein neu geschriebenes Log-Verzeichnis in der Wachstumstabelle, und ein Lauf mit --min-free 1000T gibt ALERT aus und liefert 2. Ein weiterer Test prüft, dass nur die eingestellte Zahl von Snapshots erhalten bleibt.

Es sind 14 Tests. Das CI führt sie auf Python 3.10, 3.11, 3.12 und 3.13 aus, zusammen mit ruff check und ruff format --check, und ruft das Werkzeug einmal auf dem eigenen Checkout auf.

Grenzen

  • Verzeichnisse werden nur bis zur gewählten Tiefe aufgezeichnet. Wachstum weiter unten wird dem tiefsten aufgezeichneten Verzeichnis darüber zugerechnet.
  • Nicht lesbare Verzeichnisse werden übersprungen. Für ein vollständiges Bild von / muss das Werkzeug als root laufen.
  • Andere Dateisysteme, die unterhalb der Wurzel eingehängt sind, fehlen im Ergebnis.
  • Die Wachstumstabellen brauchen frühere Snapshots. Der erste Lauf hat keine, und der Sieben-Tage-Vergleich erscheint erst, wenn ein so alter Snapshot existiert.

Code und Installationsanleitung liegen unter github.com/Jwrede/diskdelta.