Platz schaffen, Ursache finden, Wiederholung verhindern
No space left on device mitten im Live-Betrieb ist einer der unangenehmsten Alarme ueberhaupt, weil MySQL, PHP-Sessions und Logging gleichzeitig ausfallen koennen. Dieser Artikel liefert den kompletten Notfall-Workflow fuer einen vollen Datentraeger: sicher und schnell Platz schaffen, den tatsaechlichen Grossverbraucher identifizieren und danach dafuer sorgen, dass der Vorfall sich nicht wiederholt.
Inhaltsverzeichnis
- 1. Die ersten Sekunden: keine Panik-Loeschung
- 2. df -h fuer den schnellen Ueberblick
- 3. Grossverbraucher mit du und ncdu finden
- 4. Geloeschte, aber noch offene Dateien mit lsof
- 5. Sicheres Freiraeumen: Logs, Caches, Tempfiles
- 6. Wenn df noch Platz zeigt: Inode-Erschoepfung
- 7. Datenbank-Sonderfall: Binlogs und Tablespaces
- 8. Praevention: Monitoring, Quotas, Log-Rotation
- 9. Ursachen und Massnahmen im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Die ersten Sekunden: keine Panik-Loeschung
Wenn der Datentraeger voll ist und Anwendungen mit Fehlern wie No space left on device abbrechen, ist der Impuls, sofort irgendetwas zu loeschen, verstaendlich, aber gefaehrlich. Wahllos Dateien zu entfernen, ohne vorher zu wissen, wofuer sie gebraucht werden, kann eine laufende Datenbank-Transaktion beschaedigen, ein aktives Backup zerstoeren oder eine Konfigurationsdatei entfernen, die danach fehlt. Der erste Schritt bei einem vollen Datentraeger ist deshalb immer Beobachtung vor Aktion.
Ein zweiter haeufiger Fehler ist das Loeschen von Dateien, die von einem laufenden Prozess noch geoeffnet sind. Unter Linux gibt das Betriebssystem den Speicherplatz einer geloeschten Datei erst frei, wenn kein Prozess mehr einen offenen Filehandle darauf haelt. Wird eine grosse Logdatei geloescht, waehrend ein Daemon noch in sie schreibt, bleibt der Speicherplatz belegt, bis der Prozess neu gestartet wird, das Problem beim vollen Datentraeger besteht scheinbar unveraendert fort und sorgt fuer zusaetzliche Verwirrung.
2. df -h fuer den schnellen Ueberblick
Der erste konkrete Befehl bei einem vollen Datentraeger ist df -h, das die Belegung aller gemounteten Dateisysteme in menschenlesbaren Einheiten zeigt. Wichtig ist, alle Zeilen zu pruefen, nicht nur die Root-Partition: Ein separates Mount fuer /var oder /var/log kann voll sein, waehrend / selbst noch Kapazitaet hat, und umgekehrt. Gerade bei Magento-Servern mit separatem Mount fuer pub/media ist dieser Unterschied entscheidend fuer die weitere Suche.
df -hT ergaenzt zusaetzlich den Dateisystemtyp, was bei gemischten Setups mit tmpfs, overlay-Mounts fuer Docker-Container und regulaeren ext4- oder XFS-Partitionen hilft, echte physische Vollstaende von temporaeren RAM-basierten Mounts zu unterscheiden. Ein tmpfs-Mount, der voll laeuft, hat eine andere Ursache und andere Konsequenzen als ein voller physischer Datentraeger und darf in der Diagnose nicht vermischt werden.
# Step 1: check every mounted filesystem, not just root
df -hT
# Filesystem Type Size Used Avail Use% Mounted on
# /dev/sda1 ext4 50G 49G 512M 99% /
# /dev/sdb1 xfs 200G 198G 1.8G 99% /var/lib/mysql
# tmpfs tmpfs 8.0G 120M 7.9G 2% /tmp
# /var/lib/mysql is the actual bottleneck here, not root
In diesem Beispiel ist nicht die Root-Partition das eigentliche Problem, sondern das separate Mount fuer /var/lib/mysql, das ebenfalls nahezu voll ist. Wer hier ausschliesslich auf / schaut, uebersieht die kritischere Partition und riskiert, dass MySQL kurz darauf mit einem Schreibfehler abbricht, obwohl der Datentraeger insgesamt scheinbar noch Reserven hatte.
3. Grossverbraucher mit du und ncdu finden
Sobald klar ist, welches Mount tatsaechlich voll ist, folgt die Suche nach dem Grossverbraucher. du -h --max-depth=1 /var | sort -rh zeigt die groessten Unterverzeichnisse auf einer Ebene, sortiert nach Groesse. Das Vorgehen wird rekursiv wiederholt: Ist /var/log der groesste Verbraucher, folgt du -h --max-depth=1 /var/log, um innerhalb dieses Verzeichnisses weiter einzugrenzen, bis die konkrete Datei oder das konkrete Log gefunden ist.
Fuer eine schnellere und interaktive Suche eignet sich ncdu, ein textbasiertes Werkzeug, das ein Verzeichnis einmalig scannt und danach per Pfeiltasten navigierbar macht, ohne wiederholte du-Aufrufe. Bei einem akut vollen Datentraeger spart das erheblich Zeit, weil man sich von der Wurzel aus interaktiv zum groessten Verbraucher durchklickt, statt jeden Schritt manuell mit einem neuen Befehl auszufuehren.
# Recursive drill-down with du, one level at a time
du -h --max-depth=1 /var | sort -rh | head -10
# 18G /var/log
# 4.2G /var/lib/docker
# 1.1G /var/cache
du -h --max-depth=1 /var/log | sort -rh | head -10
# 14G /var/log/mysql
# 3.1G /var/log/nginx
# Interactive drill-down — faster for repeated exploration
ncdu /var/log
4. Geloeschte, aber noch offene Dateien mit lsof
Ein haeufig uebersehener Sonderfall bei einem vollen Datentraeger: du zeigt einen belegten Speicherplatz, der grosse Dateien im Dateisystem-Verzeichnisbaum aber nicht mehr auffindbar sind, weil sie bereits geloescht wurden, waehrend ein Prozess sie noch offen haelt. Der Kernel gibt den Speicherplatz erst frei, wenn der letzte Filehandle geschlossen wird, unabhaengig davon, ob die Datei aus Sicht des Dateisystems noch existiert.
lsof +L1 listet gezielt Dateien mit einem Link-Count von unter eins, also geloeschte, aber noch offene Dateien, zusammen mit ihrer Groesse und dem haltenden Prozess. Das ist bei Log-Rotation-Fehlern extrem haeufig: Ein logrotate-Lauf benennt eine Logdatei um oder loescht sie, aber der schreibende Daemon haelt weiterhin den alten Filehandle und schreibt munter in eine bereits geloeschte, aber weiterhin Platz belegende Datei hinein.
# Find deleted-but-still-open files holding disk space
lsof +L1
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
# mysqld 1842 mysql 5w REG 253,0 8.9G 0 4211 /var/log/mysql/slow.log (deleted)
# Reclaim the space by restarting or signaling the process to reopen its log file
kill -HUP 1842
Der Fix in diesem Fall ist selten, den Prozess hart zu beenden. Viele Daemons, darunter mysqld und nginx, reagieren auf SIGHUP mit einem Reopen ihrer Log-Dateihandles, was die geloeschte, aber blockierte Datei sofort freigibt, ohne den Dienst neu zu starten. Diese Technik gehoert zum Kern jedes Notfall-Workflows bei einem vollen Datentraeger, weil sie oft mehrere Gigabyte in Sekunden freigibt, ohne einen Produktivausfall zu riskieren.
5. Sicheres Freiraeumen: Logs, Caches, Tempfiles
Nach der Identifikation des Grossverbrauchers folgt das eigentliche Freiraeumen, aber auch hier gilt: gezielt statt pauschal. Alte, bereits rotierte Logdateien unter /var/log mit Endungen wie .1, .gz oder .old lassen sich in der Regel gefahrlos komprimieren oder loeschen, weil sie von logrotate bereits als abgeschlossen markiert wurden. Composer- und npm-Caches, temporaere Docker-Build-Layer sowie veraltete Kernel-Images bei apt-basierten Systemen sind weitere haeufige, risikoarme Kandidaten fuer schnelles Freiraeumen bei einem vollen Datentraeger.
Vorsicht ist geboten bei allem, was aktuell im Schreibzugriff steht: aktive Session-Dateien in /var/lib/php/sessions, laufende Backup-Archive oder Datenbank-Binlogs, die noch fuer Replikation gebraucht werden. Vor jeder Loeschung in einem produktiven System lohnt sich ein kurzer Check mit lsof auf das Zielverzeichnis, um sicherzustellen, dass kein aktiver Prozess gerade genau diese Datei benutzt.
# Safe, low-risk cleanup candidates on most Debian/Ubuntu servers
apt-get clean # cached .deb packages
journalctl --vacuum-size=200M # cap systemd journal size
find /var/log -name "*.gz" -mtime +30 -delete # old rotated logs
docker system prune -af --volumes # unused Docker images/layers
composer clear-cache
6. Wenn df noch Platz zeigt: Inode-Erschoepfung
Ein weniger bekannter Sonderfall des vollen Datentraeger: df -h zeigt freien Speicherplatz, doch das System meldet trotzdem No space left on device. In diesem Fall ist nicht der Byte-Speicherplatz erschoepft, sondern die Anzahl der verfuegbaren Inodes. Jedes Dateisystem reserviert bei der Erstellung eine feste Anzahl Inodes, und jede Datei, egal wie klein, verbraucht genau einen davon. Verzeichnisse mit Millionen winziger Dateien, etwa PHP-Session-Dateien oder Mail-Queues, erschoepfen Inodes, lange bevor der Speicherplatz selbst knapp wird.
df -i zeigt die Inode-Belegung analog zu df -h fuer Bytes. Steht dort IUse% bei 100 Prozent, muss die Anzahl der Dateien reduziert werden, nicht deren Groesse. Der Fix ist meist, veraltete Session-Dateien oder Queue-Eintraege konsequent aufzuraeumen, langfristig hilft ein separates Dateisystem fuer solche Verzeichnisse mit passend dimensionierter Inode-Anzahl bei der Neuformatierung.
7. Datenbank-Sonderfall: Binlogs und Tablespaces
Bei MySQL- und MariaDB-Servern ist eine besonders haeufige Ursache fuer einen vollen Datentraeger eine unbegrenzt wachsende Binlog-Historie. Ist expire_logs_days beziehungsweise binlog_expire_logs_seconds nicht gesetzt, sammeln sich Binlog-Dateien unbegrenzt an, besonders wenn ein Replikations-Slave laengere Zeit offline war und der Master die Logs fuer ihn vorhaelt. PURGE BINARY LOGS BEFORE mit einem konkreten Datum raeumt hier gezielt auf, ohne aktive Replikation zu gefaehrden.
Ein zweiter datenbankspezifischer Fall ist das InnoDB-Tablespace-Wachstum bei geloeschten, aber nicht wiederverwendeten Datenbereichen. Ohne innodb_file_per_table wachsen alle Tabellen in einer gemeinsamen ibdata1-Datei, die nach dem Loeschen grosser Tabellen nicht automatisch schrumpft. Ein sauberer Dump-und-Reimport in eine neu angelegte Datenbank mit aktivierter Datei-pro-Tabelle-Option ist hier oft die einzige nachhaltige Loesung fuer einen wiederkehrend vollen Datentraeger.
8. Praevention: Monitoring, Quotas, Log-Rotation
Der beste Umgang mit einem vollen Datentraeger ist, ihn gar nicht erst entstehen zu lassen. Ein Monitoring-Alarm bei 80 Prozent Belegung gibt genug Vorlaufzeit, um in Ruhe zu handeln, statt im akuten Vollstand improvisieren zu muessen. Werkzeuge wie Prometheus mit dem node_exporter oder ein einfaches Cron-Skript mit df-Auswertung und E-Mail-Versand erfuellen diesen Zweck bereits ohne grossen Aufwand.
Eine korrekt konfigurierte logrotate-Regel mit maxsize, rotate und compress verhindert, dass einzelne Logdateien unbegrenzt wachsen. Fuer Verzeichnisse mit nutzergenerierten Daten, etwa Upload-Ordner in Magento, begrenzen Dateisystem-Quotas den maximal moeglichen Verbrauch pro Benutzer oder Verzeichnis und verhindern, dass ein einzelner fehlerhafter Prozess den gesamten Datentraeger fuellen kann.
9. Ursachen und Massnahmen im Vergleich
Die folgende Tabelle ordnet die haeufigsten Ursachen fuer einen vollen Datentraeger den passenden Sofortmassnahmen und den langfristigen Praeventionsschritten zu, damit im Notfall schnell die richtige Spur verfolgt wird.
| Ursache | Sofortmassnahme | Langfristige Praevention |
|---|---|---|
| Ungerotierte Logs | du, alte Logs komprimieren/loeschen |
logrotate mit maxsize konfigurieren |
| Geloeschte, offene Datei | lsof +L1, Prozess per SIGHUP |
Log-Rotation mit copytruncate testen |
| Inode-Erschoepfung | df -i, kleine Dateien aufraeumen |
Separates Mount mit mehr Inodes |
| Wachsende Binlogs | PURGE BINARY LOGS BEFORE | binlog_expire_logs_seconds setzen |
| Docker-Layer, Images | docker system prune -af |
Regelmaessige Cron-Bereinigung |
| Volle PHP-Session-Ablage | find /var/lib/php/sessions -mmin +1440 -delete |
session.gc_maxlifetime korrekt setzen |
| Wachsende Elasticsearch-Indizes | Alte Indizes per ILM loeschen | Index Lifecycle Management konfigurieren |
Die Tabelle macht deutlich: Ein voller Datentraeger hat selten eine einzige Ursache. In der Praxis kombinieren sich oft mehrere der genannten Faktoren, etwa ungerotierte Nginx-Logs zusammen mit wachsenden MySQL-Binlogs, weshalb eine vollstaendige Diagnose immer alle Ebenen vom Dateisystem bis zur Anwendung durchlaufen sollte.
Mironsoft
Server-Monitoring, Storage-Praevention und Incident Response
Nie wieder ueberrascht von einem vollen Datentraeger?
Wir richten Monitoring mit rechtzeitigen Alarmen ein, konfigurieren Log-Rotation und Datenbank-Housekeeping und stehen bei einem akuten Vollstand fuer schnelle Notfall-Diagnose zur Verfuegung.
Storage-Monitoring
Fruehwarnung bei 80 Prozent Belegung statt Ueberraschung bei 100 Prozent
Log- und DB-Housekeeping
logrotate, Binlog-Rotation und Docker-Bereinigung sauber konfigurieren
Notfall-Support
Schnelle, risikoarme Wiederherstellung bei akutem Vollstand
10. Zusammenfassung
Ein voller Datentraeger verlangt eine feste Reihenfolge: erst beobachten mit df -hT, dann gezielt eingrenzen mit du oder ncdu, dabei geloeschte, aber offene Dateien mit lsof +L1 nicht vergessen und erst danach kontrolliert loeschen. Sonderfaelle wie Inode-Erschoepfung und wachsende Datenbank-Binlogs erfordern eigene Diagnosewege, die eine reine df -h-Betrachtung nicht aufdeckt.
Der nachhaltigste Schutz vor einem erneuten vollen Datentraeger ist Praevention: rechtzeitiges Monitoring bei 80 Prozent Belegung, konsequente Log-Rotation und automatisierte Datenbank-Housekeeping-Jobs. Wer diese drei Bausteine einmal sauber einrichtet, verwandelt einen wiederkehrenden Notfall in ein planbares Wartungsthema.
Voller Datentraeger — Das Wichtigste auf einen Blick
Erster Ueberblick
df -hT zeigt alle Mounts inklusive Typ, niemals nur die Root-Partition pruefen.
Grossverbraucher finden
du --max-depth=1 rekursiv oder ncdu interaktiv fuer schnelle Eingrenzung.
Versteckte Fallen
lsof +L1 fuer geloeschte offene Dateien, df -i fuer Inode-Erschoepfung.
Praevention
Monitoring bei 80%, logrotate mit maxsize, Binlog-Expiry und Docker-Bereinigung.