So verhindern Sie ein versehentliches rm -rf auf Linux-Servern

Setzen Sie auf mehrere Schichten, denn jede fängt einen anderen Ausrutscher ab. Lassen Sie interaktives rm mit alias rm='rm -I --preserve-root=all' nachfragen, tragen Sie Pfade, die nie verschwinden dürfen, in safe-rm ein, sichern Sie Skriptvariablen mit "${DIR:?}", machen Sie wichtige Dateien mit chattr +i unveränderlich und verschieben Sie Dateien in einen Papierkorb, statt sie zu löschen. Nichts davon ersetzt Snapshots und getestete Backups.

Würde eine einzige Rückfrage vor rm -rf auf Produktion reichen? Wardterm stellt sie auf jedem Server, den Sie als Produktion markieren. Zeigen

Aktualisiert am . rm -I, --preserve-root=all, die Aliase, die Rückfrage von zsh bei rm *, safe-rm 1.1 aus Debian, set -u, ${VAR:?}, chattr +i, trash-cli 0.24 und die Rettung über /proc und lsof liefen auf Debian-13-Containern mit GNU coreutils 9.7, bash 5.2 und zsh 5.9.

Was rm schon verweigert und was nicht

GNU rm verweigert rm -rf / von Haus aus. Das schützt genau einen Pfad. Die üblichen Unfälle sehen anders aus:

  • rm -rf /*: Die Shell erweitert zuerst den Stern, rm bekommt also /bin, /etc und den Rest, und keiner davon ist /.
  • rm -rf /var/app /*: Ein verirrtes Leerzeichen setzt das ganze System auf die Liste.
  • Eine leere Variable in einem Skript: rm -rf "$DIR"/* wird zu rm -rf /*.
  • Der richtige Befehl im falschen Terminal, auf einem Server, den Sie für Staging hielten.

--preserve-root=all geht einen Schritt weiter und verweigert jeden Ordner, der auf einer anderen Platte liegt als sein übergeordneter Ordner, etwa ein eingehängtes Volume:

rm: skipping '/dev/shm', since it's on a different device
rm: and --preserve-root=all is in effect

Gewohnheiten wie einen Glob vor dem Löschen mit echo aufzulisten finden Sie unter wie Sie Fehler auf Produktionsservern vermeiden.

Interaktives rm einmal nachfragen lassen

Schreiben Sie diese zwei Zeilen auf dem Server in ~/.bashrc und in /root/.bashrc:

alias rm='rm -I --preserve-root=all'
alias sudo='sudo '

-I fragt einmal vor einem rekursiven Löschen oder vor dem Entfernen von mehr als drei Dateien. Alles außer y entfernt nichts. Das Leerzeichen am Ende des sudo-Alias sagt bash, dass es auch das nächste Wort als Alias erweitern soll, also fragt auch sudo rm:

$ sudo rm /tmp/s/*
rm: remove 4 arguments? n

zsh fragt von sich aus vor rm * und rm pfad/*, außer RM_STAR_SILENT ist gesetzt:

zsh: sure you want to delete all 2 files in /tmp/z [yn]? n

Aliase gelten nur in interaktiven Shells. Skripte, Cron-Jobs und ssh server 'rm ...' nutzen das echte rm, und \rm oder command rm umgehen den Alias absichtlich. Verzichten Sie auf alias rm='rm -i': Eine Frage pro Datei gewöhnt Leute daran, -f zu tippen.

safe-rm: Pfade, die rm überspringt

safe-rm setzt einen Wrapper vor rm, der jeden Pfad auf einer Schutzliste überspringt. Unter Debian und Ubuntu:

sudo apt install safe-rm
echo '/srv/app/shared' | sudo tee -a /etc/safe-rm.conf

Die Liste enthält bereits Systemordner wie /etc, /usr und /var. Unser Test:

$ rm -rf /srv/app/shared
safe-rm: Skipping /srv/app/shared.

Kennen Sie die Grenzen, bevor Sie sich darauf verlassen:

  • Es schützt den eingetragenen Pfad, nicht seinen Inhalt. rm -rf /srv/app/shared/* hat den Ordner trotzdem geleert. Eine Zeile wie /srv/data/* schützt jeden Eintrag direkt unter /srv/data.
  • Es endet mit 0, auch wenn es etwas übersprungen hat, ein Skript merkt es also nicht.
  • Das Paket ergänzt PATH in /etc/profile.d um seinen Ordner, es wirkt also in Login-Shells und mit sudo -i. sudo rm nutzt den eigenen secure_path von sudo und lief in unserem Test mit dem echten rm, ebenso ssh server 'rm ...'.

Variablen in Skripten absichern

Die meisten Katastrophen in Skripten kommen von einer leeren oder nicht gesetzten Variable. Halten Sie das Skript an, bevor es rm erreicht:

#!/usr/bin/env bash
set -euo pipefail
rm -rf -- "${BUILD_DIR:?}/"
s.sh: line 3: BUILD_DIR: parameter null or not set

${BUILD_DIR:?} bricht mit einem Fehler ab, wenn die Variable leer ist oder fehlt, und set -u tut dasselbe für jede nicht gesetzte Variable im Skript. -- beendet die Optionen, sodass eine Datei namens -rf als Datei behandelt wird.

Rechte und unveränderliche Dateien

Der stärkste Schutz ist, gar nicht löschen zu können. Arbeiten Sie als normaler Benutzer und nutzen Sie sudo nur für die Befehle, die es brauchen, dann erreicht ein Ausrutscher im Home-Ordner nicht das System. Siehe wie Sie einen SSH-Benutzer mit sudo anlegen.

Für Dateien, die sich selbst für root nicht ändern dürfen, setzen Sie das Immutable-Flag, auf ext4 und anderen Dateisystemen, die es unterstützen:

sudo chattr +i /etc/app/config.yml
lsattr /etc/app/config.yml
----i---------e------- /etc/app/config.yml
rm: cannot remove '/etc/app/config.yml': Operation not permitted

Derselbe Fehler stoppte auch rm -rf auf dem umgebenden Ordner. Entfernen Sie das Flag mit sudo chattr -i vor einer geplanten Änderung. Auch Updates und Editoren können die Datei nicht schreiben, setzen Sie das Flag also nur dort, wo es wirklich nötig ist.

Ein Papierkorb statt rm

Wenn Sie von Hand aufräumen, verschieben Sie Dateien lieber in einen Papierkorb. trash-cli nutzt denselben Papierkorb wie der Linux-Desktop:

sudo apt install trash-cli
trash-put old-release/
trash-list
trash-restore
trash-empty 30

trash-restore fragt, welcher Eintrag zurück soll. trash-empty 30 entfernt, was länger als 30 Tage im Papierkorb liegt, passend für einen Cron-Job. Bis dahin belegen die Dateien weiter Speicherplatz. Machen Sie rm nicht zum Alias für trash-put: Die Optionen unterscheiden sich, und die Gewohnheit versagt auf Servern ohne das Werkzeug.

Snapshots, Backups und wenn es schon passiert ist

Jede Schicht oben lässt sich umgehen. Einen Snapshot löscht rm nicht. Legen Sie vor riskanter Arbeit einen an: zfs snapshot pool/data@before-cleanup unter ZFS, btrfs subvolume snapshot -r unter btrfs, lvcreate --snapshot mit LVM oder einen Volume-Snapshot in der Konsole Ihres Cloud-Anbieters. Kopieren Sie Backups auf einen anderen Rechner, etwa mit rsync über SSH, und testen Sie ab und zu eine Wiederherstellung.

Sind Dateien schon weg, schreiben Sie nichts mehr auf diese Platte: Neue Daten können überschreiben, was ein Rettungswerkzeug noch finden könnte. Stellen Sie dann aus Snapshot oder Backup wieder her. Ein Fall lässt sich sofort retten: eine Datei, die ein laufendes Programm noch geöffnet hat. Finden Sie sie und kopieren Sie sie zurück, bevor das Programm endet:

lsof +L1
cp /proc/374/fd/3 /root/data.recovered
COMMAND PID USER FD   TYPE DEVICE SIZE/OFF NLINK     NODE NAME
tail    374 root 3r   REG  0,186        2     0 12873355 /srv/data.txt (deleted)

Die Zahl nach /proc/ ist die PID, die nach fd/ die Zahl aus der Spalte FD ohne ihren Buchstaben.

Fragen

Funktioniert rm -rf / unter Linux noch?

Mit GNU rm nicht: Es verweigert /, außer Sie geben --no-preserve-root an. rm -rf /* erweitert die Shell aber zu /bin, /etc und dem Rest, und das wird nicht verweigert.

Kann ich rm -rf rückgängig machen?

Nicht mit rm selbst. Stellen Sie aus einem Snapshot oder Backup wieder her. Eine Datei, die ein laufendes Programm noch geöffnet hat, lässt sich aus /proc/PID/fd zurückkopieren, bis das Programm sie schließt.

Ist alias rm='rm -i' eine gute Idee?

Es fragt bei jeder Datei, also gewöhnt man sich an, ohne Lesen mit y zu antworten oder -f anzuhängen. rm -I fragt einmal, bei drei oder mehr Dateien oder beim rekursiven Löschen, und die Frage behält ihren Sinn.

Schützt safe-rm auch die Dateien in einem Ordner?

Nein. Es überspringt die Pfade aus seiner Konfiguration. rm -rf /srv/app/shared/* leert einen geschützten Ordner /srv/app/shared trotzdem, außer die Einträge darin stehen ebenfalls in der Liste, zum Beispiel mit /srv/app/shared/*.

Quellen

Mehr zu Server absichern

Alle Anleitungen