SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-13

Odzyskiwanie plików po rm -rf w systemie Linux

Usunięto dane poleceniem rm -rf? Natychmiast odmontuj system plików ext4, aby uniknąć nadpisania bloków. Sprawdź skuteczne metody odzyskiwania danych przy użyciu narzędzia extundelete.

Co zrobić w ciągu pierwszych sześćdziesięciu sekund

O odzyskaniu plików usuniętych za pomocą rm -rf decydują dwie kwestie, a obie muszą zostać rozwiązane przed otwarciem wyszukiwarki. Należy natychmiast zaprzestać zapisu w tym systemie plików. Następnie trzeba wyłączyć go z użytku poprzez odmontowanie lub ponowne zamontowanie w trybie tylko do odczytu.

rm nie usuwa żadnych danych. Polecenie to usuwa wpis w katalogu, a następnie oznacza i-węzeł oraz bloki danych pliku jako wolne. Bajty nadal znajdują się na urządzeniu. Pozostają tam, dopóki alokator bloków nie przydzieli tych bloków innemu procesowi, który nadpisze zawartość. Każda sekunda, w której system plików pozostaje zamontowany i aktywny, zwiększa ryzyko, że demon zapisze linię dziennika lub baza danych zrzuci stronę pamięci na dysk. Każdy z tych zapisów może trafić na bloki, które mają zostać odzyskane.

Dlatego pierwsze polecenia to te, które zatrzymują zapis, a nie te, które odzyskują pliki.

sudo systemctl stop nginx postgresql
sudo umount /mnt/data

Jeśli umount zwraca umount: /mnt/data: target is busy., należy zidentyfikować procesy blokujące system plików.

sudo fuser -vm /mnt/data
sudo lsof +D /mnt/data

Jeśli nie można zwolnić systemu plików, należy zamontować go ponownie w trybie tylko do odczytu. Montowanie w trybie tylko do odczytu zatrzymuje nowe alokacje, co stanowi większość niezbędnych działań.

sudo mount -o remount,ro /mnt/data

Jeśli usunięta ścieżka znajdowała się w głównym systemie plików, sytuacja jest trudniejsza. sudo mount -o remount,ro / zazwyczaj kończy się niepowodzeniem z komunikatem mount: /: cannot remount /dev/vda1 read-only., ponieważ uruchomione procesy utrzymują otwarte pliki do zapisu, a jądro nie wymusi ich zamknięcia. W przypadku VPS praktycznym rozwiązaniem jest tryb ratunkowy (rescue mode) dostarczony przez operatora: uruchamia on oddzielny system typu live z podłączonym, ale niezamontowanym dyskiem użytkownika. Wszystkie poniższe polecenia należy wtedy wykonać na urządzeniu, na którym nie odbywa się żaden zapis.

Jedna zasada dotyczy całego tego przewodnika. Nigdy nie zapisuj odzyskanych plików, obrazu dysku ani nowo zainstalowanych narzędzi w systemie plików, z którego prowadzona jest odzysk. Należy podłączyć drugi wolumin lub przesłać dane wyjściowe na inną maszynę za pośrednictwem SSH.

Dlaczego odzyskiwanie danych po rm -rf na systemie ext4 jest w większości przypadków bezskuteczne

Określ oczekiwania przed przystąpieniem do jakichkolwiek działań. Potwierdź, z jakim systemem plików masz do czynienia:

lsblk -f

W systemie ext4, domyślnym dla niemal każdego obrazu VPS, lokalizacja danych pliku jest zapisana w jego i-węźle (inode) jako drzewo zakresów (extent tree). Zakres to rekord informujący, że logiczny blok N pliku zaczyna się w fizycznym bloku M i obejmuje L bloków. Małe pliki przechowują do czterech takich rekordów bezpośrednio w i-węźle. Większe pliki wskazują na dodatkowe bloki zawierające resztę drzewa.

Gdy ostatnie dowiązanie do pliku zostaje usunięte, ext4 przeszukuje drzewo, zwraca wszystkie zakresy do alokatora bloków i czyści drzewo z i-węzła. I-węzeł zostaje oznaczony jako wolny i otrzymuje znacznik czasu usunięcia. Same dane pozostają nienaruszone. Jedyny zapis wskazujący, gdzie znajdowały się te dane, został wymazany.

Na tym polega różnica względem ext3, gdzie usunięty i-węzeł zachowywał wystarczająco dużo informacji, aby narzędzia takie jak ext3grep mogły je śledzić. Na ext4 nadal można wyświetlić usunięte i-węzły:

sudo debugfs -R lsdel /dev/vdb1

debugfs otwiera urządzenie w trybie tylko do odczytu, chyba że użyjesz flagi -w, więc jest to bezpieczne dla niezamontowanego urządzenia i nic nie kosztuje. I-węzły zostaną wyświetlone. Na tym jednak koniec, ponieważ mapa bloków, którą przechowywał i-węzeł, została wyczyszczona, więc dump nie ma czego śledzić.

Dwa narzędzia próbują obejść ten problem, odczytując dziennik (journal). Dziennik to pierścieniowy bufor o stałym rozmiarze, którego ext4 używa do utrzymania spójności metadanych w razie awarii; może on nadal zawierać starszą kopię i-węzła sprzed usunięcia. Zarówno extundelete, jak i ext4magic przeszukują go. Sprawdź, z jakim rozmiarem pracujesz:

sudo dumpe2fs -h /dev/vdb1 | grep -i journal

Dziennik przechowuje tylko metadane i jest niewielki, więc zwykła aktywność zapisu nadpisuje go bardzo szybko. Na działającym serwerze okno czasowe, w którym i-węzeł sprzed usunięcia jeszcze istnieje, mierzy się w minutach. Żadne z tych narzędzi nie jest aktywnie rozwijane i nie każde znajduje się w repozytoriach każdej dystrybucji. Traktuj oba jako mało prawdopodobne rozwiązanie, uruchamiaj je na niezamontowanym urządzeniu lub obrazie dysku i nie zdziw się, jeśli nie zwrócą żadnych wyników.

Jeśli lsblk -f zgłasza xfs, sytuacja nie wygląda lepiej, ponieważ dla XFS również nie istnieje wspierana metoda odzyskiwania usuniętych plików. Kolejność poniższych opcji pozostaje bez zmian.

Czy plik jest nadal otwarty w działającym procesie?

Jest to jedyna metoda odzyskiwania na tej stronie o wysokiej skuteczności i stanowi powód, dla którego nie należy restartować usługi korzystającej z pliku.

Plik jest trwale usunięty dopiero wtedy, gdy dwa liczniki osiągną zero: liczba wpisów w katalogu wskazujących na jego inode oraz liczba otwartych deskryptorów plików. rm redukuje pierwszy licznik do zera. Jeśli proces nadal utrzymuje plik jako otwarty, drugi licznik nie wynosi zero, więc inode oraz jego bloki pozostają zaalokowane, a dane są nadal możliwe do odczytania.

Znajdź otwarte pliki, których licznik dowiązań spadł do zera:

sudo lsof +L1

+L1 oznacza wyświetlenie otwartych plików z licznikiem dowiązań poniżej 1. Każde dopasowanie wskazuje proces, numer deskryptora pliku, NLINK typu 0 oraz ścieżkę kończącą się (deleted). Użyj PID oraz numeru deskryptora, aby przejść do /proc:

sudo ls -l /proc/1234/fd

Wpis wygląda jak 3 -> /var/log/app/events.log (deleted). To dowiązanie nadal prowadzi do danych. Skopiuj je na inny system plików:

sudo cp /proc/1234/fd/3 /mnt/rescue/events.log

Użyj cp, a nie mv. Otwarcie /proc/1234/fd/3 zapewnia nowy uchwyt do tego samego inode, zaczynający się od offsetu zero, dzięki czemu otrzymasz cały plik, a nie tylko fragment po bieżącej pozycji zapisu.

Warto znać dwa ograniczenia. Usunięte drzewo katalogów nie zostanie w ten sposób przywrócone, ponieważ utrzymywane są tylko poszczególne pliki otwarte przez proces. Ponadto plik bazy danych skopiowany w trakcie zapisu przez silnik jest kopią typu crash-consistent, dlatego należy zaplanować uruchomienie wbudowanej procedury odzyskiwania silnika, zamiast traktować plik jako spójny. Wpisy, które lsof pokazuje z mem zamiast numeru deskryptora, są mapowane w pamięci (memory mapped) i nie posiadają wpisu /proc/<pid>/fd, z którego można by wykonać kopię.

Czy posiadasz snapshot na btrfs, ZFS lub LVM?

Jeśli system plików obsługuje snapshoty, usunięte pliki znajdują się wewnątrz jednego z nich w niezmienionej formie. Jest to przydatne tylko wtedy, gdy snapshot istniał przed usunięciem danych. Żadne działanie podjęte w tej chwili nie przywróci danych wstecz.

btrfs przechowuje snapshoty jako subwolumeny:

sudo btrfs subvolume list /

Przeglądaj snapshot i skopiuj potrzebne ścieżki za pomocą cp -a. Zaleca się kopiowanie pojedynczych ścieżek zamiast przywracania całego subwolumenu, ponieważ przywrócenie (rollback) powoduje również utratę wszystkich danych zapisanych od momentu wykonania snapshota.

ZFS udostępnia każdy snapshot jako katalog tylko do odczytu:

zfs list -t snapshot
ls /tank/data/.zfs/snapshot/

Katalog .zfs jest ukryty i nie pojawi się w zwykłym ls katalogu głównego zbioru danych (dataset), ale można wejść do niego bezpośrednio po nazwie. Skopiuj stamtąd pliki. zfs rollback przywraca cały zbiór danych i niszczy wszystkie snapshoty nowsze od wskazanego, dlatego należy traktować to jako ostateczność.

Snapshoty LVM to wolumeny typu copy-on-write o stałym rozmiarze:

sudo lvs
sudo mount -o ro /dev/vg0/data-snap /mnt/snap

Zamontuj go w trybie tylko do odczytu i skopiuj dane. Sprawdź lvs przed użyciem, ponieważ snapshot LVM, który zapełni przydzielone miejsce, jest unieważniany przez jądro systemu, a po wystąpieniu takiej sytuacji jego zawartość jest nieodwracalnie utracona.

Snapshot nie jest kopią zapasową. Znajduje się na tym samym dysku lub w tej samej puli co oryginał, więc współdzieli z nim wszelkie awarie. Jest bardzo skuteczny w cofaniu błędów popełnionych przed chwilą, co jest dokładnie celem tego zadania.

Odzyskiwanie danych za pomocą PhotoRec, wyłącznie z obrazu dysku, nigdy z działającego nośnika

Jeśli powyższe metody nie przynoszą rezultatu, pozostaje carving: skanowanie surowego urządzenia w poszukiwaniu wzorców bajtów oznaczających początek znanego typu pliku, a następnie zapisywanie wszystkiego, co po nich następuje. Carving odczytuje wyłącznie dane plików. Nazwy plików, struktura katalogów, znaczniki czasu i informacje o właścicielu to metadane systemu plików, a te zostały zniszczone przez rm, więc nie da się ich odzyskać. Otrzymasz pliki o nazwach f0384512.jpg w ponumerowanym katalogu wyjściowym, które trzeba posortować ręcznie.

O powodzeniu decydują dwie zasady.

Po pierwsze, wykonaj obraz urządzenia, zanim skierujesz na nie jakiekolwiek inne narzędzie. W systemach Debian i Ubuntu pakiet nazywa się gddrescue, a instalowany przez niego plik binarny to ddrescue.

sudo apt update && sudo apt install -y gddrescue testdisk
sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map

/mnt/rescue musi znajdować się na innym urządzeniu, które posiada co najmniej tyle wolnego miejsca, ile zajmuje partycja. lsblk -b wyświetla dokładne rozmiary w bajtach. Plik mapy pozwala wznowić przerwane kopiowanie zamiast zaczynać od nowa. Gdy posiadasz obraz, możesz później wypróbować drugie narzędzie na dokładnie tych samych bajtach, co jest niemożliwe, jeśli pierwsze narzędzie nadpisało dysk.

Po drugie, skieruj narzędzie do odzyskiwania na plik obrazu.

sudo photorec /d /mnt/rescue/recup /mnt/rescue/vdb1.img

photorec otwiera menu tekstowe. Wybierz partycję, następnie typ systemu plików, sygnatury plików do wyszukania, a na końcu katalog docelowy. Przed rozpoczęciem zawęź listę sygnatur do typów plików, które faktycznie utraciłeś, ponieważ domyślna lista znajduje wszystko i dostarczy dziesiątki tysięcy fragmentów do przejrzenia.

testdisk, z tego samego pakietu, posiada własną funkcję przywracania plików i obsługuje wyłącznie FAT, exFAT, NTFS oraz ext2. W przypadku ext4 pozostaje photorec.

Należy oczekiwać, że pofragmentowane pliki zostaną odzyskane jako uszkodzone. Carving zakłada, że bloki pliku są ciągłe, więc plik, który alokator rozproszył po dysku, zostanie albo błędnie złożony, albo całkowicie pominięty. Pliki multimedialne odzyskują się dość dobrze, ponieważ posiadają wyraźne nagłówki. Zwykły tekst, pliki konfiguracyjne i kod źródłowy odzyskują się słabo, ponieważ nie istnieje sygnatura bajtowa oznaczająca początek skryptu powłoki.

Zbędna spacja: jak doszło do usunięcia niewłaściwej ścieżki

Prawie każdy wypadek z rm -rf wynika z problemów z powłoką. rm otrzymuje listę ścieżek i usuwa każdą z nich po kolei. Narzędzie nie interpretuje intencji użytkownika.

Klasycznym przykładem jest pojedyncza spacja:

rm -rf /home/deploy/app /old
rm -rf /home/deploy/app/old

Pierwsza linia zawiera dwa argumenty. Polecenie usuwa aplikację, a następnie usuwa /old. Jeśli /old nie istnieje, rm nie wyświetla żadnego komunikatu, ponieważ -f wycisza błąd o brakującym pliku. Brak komunikatu nie oznacza potwierdzenia operacji.

Drugi przypadek to nieujęta w cudzysłów zmienna zawierająca spację:

dir="/srv/my app"
rm -rf $dir

Powłoka dzieli wartość w miejscu białych znaków, więc rm otrzymuje /srv/my oraz app jako dwie oddzielne ścieżki. Zapisane jako rm -rf "$dir", stanowiłoby jedną ścieżkę.

Trzeci przypadek to pusta zmienna, zazwyczaj wynikająca z niepowodzenia polecenia, które powinno ją wypełnić:

rm -rf "$TARGET"/*

Gdy TARGET nie jest ustawione, wyrażenie rozwija się do rm -rf /*. GNU rm odmawia wykonania operacji w tej formie: rm -rf / wyświetla rm: it is dangerous to operate recursively on '/' i przerywa działanie. Wariant z użyciem wzorca (glob) nie posiada takiej ochrony, ponieważ powłoka zastępuje /* listą rzeczywistych ścieżek najwyższego poziomu, zanim rm zostanie uruchomione, a / nie znajduje się na tej liście, więc zabezpieczenie nie zostaje aktywowane.

Nawyki zapobiegające kolejnym awariom

  • Każda zmienna używana jako ścieżka musi być ujęta w cudzysłów. Za każdym razem wpisuj "$dir", również wewnątrz testów i pętli.
  • Przerywaj działanie, gdy zmienna jest pusta. rm -rf "${TARGET:?TARGET is not set}"/* powoduje zatrzymanie powłoki z Twoim komunikatem przed uruchomieniem rm, jeśli TARGET nie jest ustawiona lub jest pusta. Umieść set -euo pipefail na początku każdego skryptu, który usuwa dane.
  • Dodaj --one-file-system. Instrukcja ta nakazuje rm pomijanie katalogów znajdujących się w innym systemie plików niż podany argument, dzięki czemu rekurencyjne usuwanie nie przejdzie do zamontowanego wolumenu kopii zapasowej ani punktu montowania typu bind.
  • Nie usuwaj plików jako root. Konto serwisowe może zniszczyć tylko to, co do niego należy, co stanowi główny argument za uruchamianiem każdej usługi jako osobny użytkownik bez uprawnień administracyjnych. Jeśli nie masz pewności, do czego dane konto ma dostęp, odczytanie bitów uprawnień w listingu ls odpowie na to pytanie za pomocą jednego polecenia.
  • Wyświetl listę przed wykonaniem operacji. W skrypcie zbuduj ścieżki, użyj printf '%s\n', sprawdź wynik, a następnie usuń pliki w drugim przebiegu.
  • Miej pod ręką polecenie do obsługi kosza. sudo apt install trash-cli udostępnia trash-put, trash-list, trash-restore oraz trash-empty. Usunięte pliki trafiają do ~/.local/share/Trash, a trash-empty 30 czyści wszystko, co jest starsze niż trzydzieści dni.

Aliasowanie rm do trash-put wydaje się oczywistym kolejnym krokiem, ale jest pułapką. Alias wyrabia odruch, który zawiedzie na kolejnym serwerze, gdzie go nie ma, a aliasy nie działają wewnątrz skryptów, czyli tam, gdzie dochodzi do kosztownych błędów. Wpisuj trash-put świadomie.

Jedyna metoda odzyskiwania danych, która zawsze działa

Wszystkie powyższe rozwiązania to kwestia przypadku. Backup nie jest kwestią przypadku.

Dwie rzeczy czynią backup rzeczywistym. Uruchamia się on zgodnie z harmonogramem bez konieczności pamiętania o nim oraz przynajmniej raz przeprowadzono z niego proces przywracania danych. Repozytorium, z którego nigdy nie odzyskiwano danych, jest jedynie wiarą, ponieważ czynniki czyniące je bezużytecznym (błędna ścieżka na liście uwzględniania lub hasło do repozytorium, którego nikt nie zapisał) ujawniają się dopiero w dniu, w którym są potrzebne.

W przypadku restic przywracanie danych to dwa polecenia.

restic -r /srv/restic-repo snapshots
restic -r /srv/restic-repo restore latest --target /mnt/rescue --include /srv/appdata

Przywracaj dane do pustego katalogu, a nie bezpośrednio na aktywną ścieżkę, aby móc porównać obie lokalizacje przed przeniesieniem plików. Konfiguracja backupów restic na VPS opisuje przygotowanie repozytorium oraz timer systemd, który je obsługuje.

W przypadku Borg:

borg list /srv/borg-repo
borg extract /srv/borg-repo::daily-2026-08-08 srv/appdata

Ścieżki wewnątrz archiwum Borg są przechowywane bez wiodącego ukośnika, więc srv/appdata pasuje, a /srv/appdata nie pasuje do niczego. borg extract zapisuje dane w bieżącym katalogu roboczym, więc najpierw przejdź cd do katalogu tymczasowego.

Jeśli jeszcze nie dokonano wyboru między tymi narzędziami, porównanie restic i Borg omawia deduplikację oraz repozytoria typu append-only, czyli właściwość, która uniemożliwia przejętemu serwerowi usunięcie własnej historii backupów. Oba narzędzia są odpowiednie. Błędną odpowiedzią jest brak uruchomienia któregokolwiek z nich.

Nowy serwer to najtańszy moment na konfigurację tego procesu, zanim znajdzie się na nim cokolwiek, co warto stracić. Pierwsze dziesięć minut na nowym VPS to miejsce, w którym należy wykonać tę pracę, obok konfiguracji SSH i firewalla.

Następnie dodaj cykliczny wpis w kalendarzu: raz w miesiącu przywróć jeden katalog z repozytorium do /tmp i sprawdź zawartość plików. Ten jeden nawyk jest wart więcej niż wszystkie narzędzia opisane na tej stronie.

FAQ

Czy można przywrócić usunięty plik na ext4?

Zazwyczaj nie. Gdy usuwane jest ostatnie dowiązanie do pliku, ext4 czyści drzewo zakresów (extent tree) z inoda, więc na dysku nie pozostaje żaden zapis o lokalizacji danych. extundelete oraz ext4magic przeszukują dziennik ext4 w poszukiwaniu starszej kopii inoda, co pomaga tylko wtedy, gdy usunięcie nastąpiło kilka minut temu, a system plików pozostawał w tym czasie nieaktywny. Żaden z tych projektów nie jest aktywnie rozwijany. Uruchamiaj je wyłącznie na niezamontowanym urządzeniu lub obrazie dysku, nigdy na zamontowanym systemie plików, a wcześniej sprawdź, na czym pracujesz, używając sudo dumpe2fs -h /dev/vdb1 | grep -i journal.

Usługa nadal ma otwarty usunięty plik. Czy mogę go odzyskać?

Tak, jest to najlepszy możliwy scenariusz. Dopóki proces trzyma plik otwarty, jego inod i bloki danych pozostają przydzielone, więc dane są nadal możliwe do odczytania. Nie restartuj usługi, ponieważ zamknięcie ostatniego deskryptora sfinalizuje usunięcie. Uruchom sudo lsof +L1, aby wyświetlić otwarte pliki z liczbą dowiązań równą 0, zanotuj PID oraz numer deskryptora pliku, a następnie skopiuj dane przez /proc za pomocą sudo cp /proc/1234/fd/3 /mnt/rescue/events.log. Kopię zapisz na innym systemie plików. Wpisy oznaczone przez mem zamiast numeru deskryptora są mapowane w pamięci i nie posiadają ścieżki /proc/<pid>/fd, z której można by je skopiować.

Dlaczego należy wykonać obraz dysku zamiast uruchamiać narzędzie do odzyskiwania bezpośrednio na nim?

Ponieważ każde narzędzie musi gdzieś zapisać wynik swojej pracy, a zapis na systemie plików, z którego odzyskujesz dane, może nadpisać wolne bloki, w których nadal znajdują się Twoje dane. Najpierw skopiuj partycję na inne urządzenie za pomocą sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map, a następnie skieruj photorec na plik obrazu. Obraz pozwala również na późniejsze użycie innego narzędzia na dokładnie tych samych bajtach, co jest niemożliwe, gdy cokolwiek nadpisze oryginał.

Czy rm -rf / nadal niszczy system Linux?

Samo polecenie w tej formie nie. GNU rm odmawia wykonania go i wyświetla rm: it is dangerous to operate recursively on '/'. Niebezpieczne są warianty, które powstają w inny sposób. rm -rf "$TARGET"/* przy niezdefiniowanym TARGET rozwija się do rm -rf /*, a powłoka przekazuje do rm listę rzeczywistych katalogów najwyższego poziomu, z których żaden nie jest /, więc zabezpieczenie nigdy się nie aktywuje. Zapisz "${TARGET:?TARGET is not set}", a powłoka zatrzyma się przed uruchomieniem rm.

Czy migawka (snapshot) systemu plików to kopia zapasowa?

Nie. Migawka btrfs lub ZFS znajduje się w tej samej puli co dane, które chroni, więc awaria dysku lub zniszczenie puli usuwa oba elementy jednocześnie. Migawka LVM ma dodatkowy problem w postaci stałego rozmiaru: gdy się zapełni, jądro ją unieważnia i jej zawartość przepada. Migawki są doskonałe do cofnięcia usunięcia sprzed dwóch minut. Do wszystkich innych celów przechowuj repozytorium na oddzielnym sprzęcie.

#linux#rm#data-recovery#backups#ext4