rm * ~
. Już za późno, zauważyłeś dodatkową spację w
poleceniu. Właśnie skasowałeś całe swoje dzieło !
Nadchodzi pomoc. Dokument ten wyjaśnia jak odzyskiwać skasowane pliki w
systemie plików Second Extended File System. Może uda Ci się jednak opublikować Twój genialny program.
Dokument ten został napisany w standardzie ISO-8859-2.
Oryginał tego dokumentu znajduje się pod adresem
http://pobox.com/~aaronc/.
To mini-Howto stara się dostarczyć porad jak odzyskiwać skasowane pliki w systemie plików ext2. Zawiera ono również dyskusję, jak przede wszystkim, nie dopuścić do skasowania ważnych plików.
Chciałbym, aby było ono przydatne dla ludzi, którym zdarzył się mały wypadek z
rm
; jakkolwiek mam również nadzieję, że przeczytają je także inni.
Nigdy nie wiadomo, pewnego dnia, któraś z zamieszczonych tu informacji z może
uratować Ci tyłek.
Tekst ten zakłada ogólną podstawową wiedzę o systemie plików UNIX-a. Mam jednak nadzieję, że będzie dostępny dla większości użytkowników Linux-a. Jeśli jesteś całkowicie początkujący, obawiam się, że odzyskiwanie plików wymaga ilości wiedzy technicznej, której nie posiadasz.
Nie będziesz mógł odtwarzać skasowanych plików z systemu plików ext2 bez praw
odczytu do urządzenia, na którym były one przechowywane. Ogólnie oznacza to,
że musisz być administatorem (root). Niektóre dystrybucje (takie jak
Debian GNU/Linux) tworzą
grupę disk
, której członkowie mają dostęp do takich urządzeń.
Będziesz potrzebował także debugfs
z pakietu e2fsprogs
.
Prawdopodobnie jest on już zainstalowany przez Twoją dystrybucję.
Dlaczego to napisałem? Wynikło to głównie z moich własnych doświadczeń ze
zwykłą głupotą i katastrofą spowodowaną przez komendę rm -r
wykonywaną
z prawami administratora. Skasowałem 97 plików typu JPEG, których potrzebowałem
i których prawie na pewno nie można było odzyskać z innych źrodeł. Z pomocą
użytecznych wskazówek (patrz rozdział
Wyrazy uznania i Bibliografia) i dużej wytrwałości, odzyskałem 91 nieuszkodzonych
plików. Udało mi się odtworzyć częściowo następne pięć (wystarczająco, aby
zobaczyć co było na tych obrazkach). Tylko jednego nie byłem w stanie obejrzeć,
ale nawet w tym przypadku, jestem prawie pewien, ze stracone zostały nie wiecej
niż 1024 bajty (niefortunnie z samego poczatku pliku; uwzględniając to,
że nic nie wiem o formacie JPG, zrobiłem wszystko co mogłem).
W dalszych rozważaniach będę chciał przedstawić jakiej wielkości współczynnika odtworzenia skasowanych plików możesz się spodziewać.
Istnieją następujące upublicznione wersje tego dokumentu (i daty ich publikacji):
Jakie zmiany zostały zrobione w tej wersji? Przede wszystkim, został poprawiony błąd w przykładowym odzyskiwaniu pliku. Dziękuję wszystkim, którzy napisali, żeby wskazać mi ten błąd. Mam nadzieję, że nauczyłem się być bardziej uważnym przy interakcyjnej pracy z programem.
Po drugie, rozważania o systemie plików w UNIX-ie zostały przerobione tak, aby uczynić je bardziej zrozumiałymi. Od początku nie byłem z tego zadowolony i dostałem komentarze, że nie było to napisane zbyt jasno.
Po trzecie, uuencode'owany gzip-owany tar-owany pakiet fsgrab
ze środka
pliku został usunięty. Teraz program dostępny jest na
mojej stronie domowej
i na
Metalab-ie
(i kopiach, w Polsce -
Sunsite
).
Po czwarte, dokument ten został przetłumaczony na język składu SGML używany w Linux Documention Project. Ten język może być łatwo konwertowany do innych języków składu (np. HTML-a i LaTeX-a) w celu dogodnego sposobu wyświetlania i drukowania. Jedną z korzyści z tego jest to, że ładny wygląd wersji papierowej jest łatwiejszy do osiągniecia. Inną jest to, że dokument zawiera wewnętrzne i zewnętrzne odnośniki, gdy oglądany jest przez WWW.
egil@kvaleberg.no,
który wskazał na polecenie dump
w debugfs
. Jeszcze raz, dzięki
Egil.
Druga zmiana polegała na zaznaczeniu, że użycie chattr
pomaga uniknąć
skasowania ważnych plików. Dziekuję Hermanowi Suijs
H.P.M.Suijs@kub.nl
za zauważenie tego.
Streszczenie zostało uaktualnione. Zostały dodane URL-e do organizacji i
oprogramowania. Wprowadzono wiele innych mniejszych zmian (literówki i tym
podobne).
Pomimo, że jest to pierwsza wersja od 17 miesięcy, jest tutaj mało
nowego. W wersji tej poprawione są drobniejsze błędy (literówki, puste
URL-e, tego typu rzeczy -- szczególnie nie związane z Open Group),
uaktualniono kilka części tekstu, które uległy przeterminowaniu, takich jak
partie dotyczące wersji jądra i lde
. No i zmieniłem `Sunsite' na
`Metalab'.
To wydanie jest przewidywane jako ostatnie przed wersją 2.0, która, mam nadzieję, będzie pełnym Howto. Pracuję nad istotnymi zmianami, które spowodują zwiększenie głównego numeru wersji.
Najnowsza publiczna wersja tego dokumentu powinna być zawsze dostępna na Linux Documentation Project site (i kopiach, w Polsce - Sunsite ).
Najbardziej aktualna wersja jest również przechowywana na mojej stronie domowej w kilku formatach:
Trzeba pamiętać, że Linux różni się od MS-DOS jeśli chodzi o kasowanie plików. W MS-DOS (jak i w Windows 95), dosyć łatwo jest odzyskać skasowane pliki - `system operacyjny' (używam tego terminu dosyć swobodnie) dostarcza nawet narzędzi, które automatyzują ten proces. W Linux-ie jest inaczej.
Reguła numer jeden (podstawowa wskazówka) brzmi:
RÓB KOPIE ZAPASOWE
bez względu na wszystko. Pomyśl o wszystkich swoich danych. Być może, jak ja, trzymasz kilkuletni zbiór listów, kontaktów, programów, dokumentów na swoim komputerze. Pomyśl co by się stało z Twoim życiem, gdyby Twój dysk uległ katastrofalnemu uszkodzeniu, lub gdyby -- o wielkie nieba ! -- złośliwy craker wyczyścił Twój dysk. To nie jest niemożliwe; korespondowałem z wieloma ludźmi w takiej sytuacji. Myślę, że teraz wszyscy rozsądnie myślący użytkownicy Linux-a wyjdą, kupią urządzenie do robienia kopii zapasowych, opracują kalendarz archiwizacji i będą się jego trzymać. Ja używam wolnego dysku twardego w innym komputerze i okresowo kopiuję tam przez sieć ethernet mój katalog domowy. Więcej informacji o planowaniu kalendarza archiwizacji znajdziesz u Frischa (1995) (patrz rozdział Bibliografia i Wyrazy Uznania).
Co wtedy, gdy nie ma kopii zapasowej? (lub nawet przy istnieniu kopii zapasowej: żadne środki bezpieczeństwa nie są złym rozwiązaniem w miejscu gdzie przechowywane są ważne dane).
Spróbuj ustawić prawa dostępu do ważnych plików na 440 (lub mniej):
odebranie sobie samemu praw zapisu oznacza, że rm
będzie wymagał
potwierdzenia przed skasowaniem. (Zauważyłem, że jeśli rekursywnie kasuję
katalog rm -r
, prośba potwierdzenia pojawi się przy pierwszym i drugim
pliku, potem program zachowuje się jak rm -rf
).
Niezłą sztuczką dla wybranych plików jest utworzenie w ukrytym katalogu
twardych dowiązań do nich. Kiedyś usłyszałem historię o administatorze,
który przez pomyłkę skasował /etc/passwd
(nieomal w ten sposób
niszcząc system).
Jednym z rozwiązań takiego kłopotu jest zrobienie czegoś następującego (jako
root):
# mkdir /.backup
# ln /etc/passwd /.backup
Teraz skasowanie pliku wymaga większego wysiłku: gdy napiszesz tylko
# rm /etc/passwd
wtedy
# ln /.backup/passwd /etc
odtworzy Twój plik. Oczywiście, to rozwiązanie nie pomoże jeśli nadpiszesz plik, więc nie zapomninaj o kopii zapasowej.
W systemie plików ext2 jest możliwe użycie atrybutów ext2, aby ochraniać
pliki. Atrybuty te mogą być zmieniane za pomocą komendy chattr
.
Istnieje atrybut `append-only`: plik z tym atrybutem może być tylko
powiększany, nie może być skasowany i istniejąca zawartość nie może być
nadpisana. Jeśli atrybut ten ma katalog, każdy plik czy katalog w nim leżący
może być normalnie modyfikowany, ale żaden z plików nie może zostać skasowany.
Atrybut `append-only' ustawia się poleceniem
$ chattr +a FILE...
Istnieje również atrybut `immutable', który może być zapalany lub gaszony tylko przez administratora. Pliku lub katalogu z tym atrybutem nie można zmienienić, skasować, zmienić jego nazwy, czy utworzyć do niego twardego dowiązania. Można go ustawić w następujący sposób:
# chattr +i FILE...
Ext2fs dostarcza również atrybutu `undeletable' (+u
in chattr
).
Założenie było takie, że plik z tym atrybutem po skasowaniu zostaje
przeniesiony w bezpieczne miejsce `safe location', aby rzeczywiste
skasowanie przesunąć w czasie. Niestety funkcja ta nie jest jeszcze
zaimplementowana w jądrze. Myślałem, że będzie większe zainteresowanie nią
i stanie się to szybko, ale nie jest ona dostępna (według mojej wiedzy) w
żadnej aktualnej wersji jądra.
Niektórzy radzą, aby zrobić alias lub funkcję w powłoce rm
, która
wykonywałaby rm -i
(będziesz musiał potwierdzić skasowanie
każdego pliku).
Dystrubucja Red Hat robi to domyślnie dla wszystkich użytkowników, w tym i dla root-a.
Ja osobiście nie lubię oprogramowania, które nie może działać bez mojej
pomocy, dlatego nie używam tego sposobu. Wcześniej, czy później może pojawić
się kolejny problem: kiedy będziesz pracował w trybie singe-user, lub
będziesz używał innej powłoki lub nawet innej maszyny, gdzie Twoja funkcja
rm
nie istnieje. Jeśli będziesz spodziewał się, że każde skasowanie
wymaga potwierdzenia, dosyć łatwo jest nie przewidzieć tego, że kazałeś
skasować zbyt wiele plików. Również skrypty i programy, które podmieniają
rm
mogą być bardzo niebezpieczne.
Trochę lepszym rozwiązaniem jest użycie pakietu, który umożliwia
`odtwarzalne' kasowanie poprzez specjalną komendę zastępująca rm
.
Szczegóły znajdziesz u Peeka (1993) (patrz rozdział
Bibliografia i Wyrazy Uznania). Jednak w ten
sposób przyzwyczajamy użytkownika do pewniej nonszalancji przy kasowaniu
plików. Nie jest to najlepsze, bowiem system typu Unix wymaga jednak uważnego
działania.
To zależy. Problem wynika z tego, że w systemie operacyjnym wysokiej jakości, wielozadaniowym, wieloużytkownikowym, takim jak Linux, nie możesz przewidzieć kiedy ktoś zechce zapisać coś na dysk. Po chwili, w której kazałeś systemowi skasować jakiś plik, bloki przez niego zajęte mogą zostać użyte, gdy system będzie chciał zapisać coś nowego. (Jest to jeden przykład ogólnej zasady systemów typu Unix: jądro i związane z nim programy zakładają, że użytkownicy nie są idiotami). Ogólnie rzecz biorąc, im bardziej obciążona jest Twoja maszyna, tym mniej prawdopodobne jest odzyskanie plików.
Znaczenie może mieć również fragmentacja dysku. Jeśli partycja, na której był skasowany plik jest bardzo pofragmentowana, masz małe szanse na odczytanie całej jego treści.
Jeśli Twój komputer, tak jak mój, realnie jest maszyną jednoużytkownikową i nie robiłeś niczego co intensywnie korzystało z dysku w tragicznej chwili skasowania pliku, możesz się spodziewać współczynnika odzysku zbliżonego do tego wymienionego niżej. Ja odzyskałem prawie 94% plików (były to pliki binarne) w stanie nieuszkodzonym. Jeżeli otrzymasz 80% lub więcej, myślę, że będziesz z siebie zadowolony.
Operacja ta polega głównie na znalezieniu danych na urządzeniu partycji i uczynieniu ich ponownie widocznymi dla systemu operacyjnego. Są dwa sposoby, żeby to zrobić: pierwszy polega na takiej zmianie systemu plików, żeby usunąć znacznik `deleted' ze skasowanych iwęzłów z nadzieją, że pliki nagle pojawią się na swoim miejscu. Inną metodą, bezpieczniejszą, ale wolniejszą jest znalezienie położenia interesujących danych na partycji i zapisaniu ich jako nowy plik w innym systemie plików.
Przed odtwarzeniem danych musisz zrobić kilka rzeczy; patrz rozdziały Odmontowanie systemu plików, Przygotowanie do bezpośrednich zmian w iwęzłach i Przygotowanie do zapisania danych w innym miejscu. Informację jak odzyskiwać pliki znajdziesz w rozdziałach Szukanie skasowanych iwęzłów, Uzyskiwanie szczegółowych informacji o iwęzłach, Odzyskiwanie bloków danych i Bezpośrednie modyfikacje iwęzłów.
Niezależnie od metody jaką wybrałeś, pierwszym krokiem jest odmontowanie systemu plików zawierającego skasowane pliki. Zdecydowanie nie polecam żadnych działań na zamontowanym systemie plików. Krok ten powinien być wykonany najszybciej jak to będzie możliwe od momentu, gdy zauważyłeś, że pomyłkowo skasowałeś pliki. Im szybciej odmontujesz system plików, tym większa będzie szansa, że Twoje dane nie zostaną nadpisane (zamazane).
Najprostszą metodą, aby to zrobić jest: zakładając, że
skasowane pliki były systemie plików /usr
,
# umount /usr
Jeśli chcesz możesz również utrzymać widoczność katalogu /usr
.
Zamontuj go w trybie tylko-do-odczytu:
# mount -o ro,remount /usr
W przypadku, gdy skasowane pliki były na głównej partycji musisz dodać opcję
-n
, aby zabronić programowi mount
na próby zapisu do
/etc/mtab
:
# mount -n -o ro,remount /
Poza tym wszystkim, możliwe jest również, że jakiś inny proces używa
interesującego nas systemu plików (spowoduje to błąd typu `Resource busy'
przy próbie odmontowania). fuser
jest programem, który wyśle sygnał do
każdego procesu używającego wskazanego pliku lub punktu montowania. Spróbuj
tego dla partycji /usr
:
# fuser -v -m /usr
W ten sposób uzyskasz listę przeszkadzających Ci procesów. Zakładając, że żaden z nich nie jest niezbędny, możesz napisać
# fuser -k -v -m /usr
aby wysłać sygnał SIGKILL
do każdego z nich ( gwarantuje to ich zabicie),
albo
# fuser -k -TERM -v -m /usr
aby przekazać każdemu sygnał SIGTERM
(spowoduje to normalne zakończenie
pracy procesów).
Moja rada? Nie używaj tej metody. Nie uważam, żeby dobrym pomysłem była zabawa na niskim poziomie w systemie plików. Metoda ta stwarza również problemy jeśli chcesz odtworzyć pliki większe niż 12 bloków. W celu odzyskania dużych plików, tak czy owak, będziesz musiał użyć innej metody. (Chociaż patrz rozdział Czy będzie to kiedyś łatwiejsze? w celu dodatkowych informacji.)
Jeżeli jednak chcesz koniecznie użyć tego sposobu, lepiej skopiuj bezpośrednio obraz partycji na inną partycję, a później zamontuj ją używając pętli zwrotnej (loopback):
# cp /dev/hda5 /root/working
# mount -t ext2 -o loop /root/working /mnt
(Niektóre wersje mount
nie potrafią tego zrobić. Jeśli Twój mount
nie działa poprawnie, zalecam użycie najnowszej wersji, conajmniej 2.7. Dużo
starsze wersje mają problemy z utrzymaniem bezpieczeństwa danych.)
Używając pętli zwrotnej, nawet jeśli całkowicie zniszczysz system plików, możesz ponownie skopiować partycję i zacząć próby od nowa.
Jeżeli wybierzesz tę drogę działania, musisz znaleźć partycję ratunkową
-- miejsce, gdzie zapiszesz nowe kopie odzyskanych plików. Na całe
szczęście, twój system zawiera kilka partycji: prawdopodobnie partycję
główną, /usr
i /home
. Wybierz jedną z nich i utwórz na
niej nowy katalog.
Jeśli masz tylko partycję główną i wszystko przechowujesz na niej, rozwiązanie troszkę się skomplikuje. Może masz partycje MS-DOS lub Windows, której bedziesz mógł użyć ? Albo masz sterownik do ramdisk-u w swoim jądrze, albo w module ? W celu użycia ramdisk-u (zakładając, że jądro jest nowsze od 1.3.48), napisz:
# dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
# mke2fs -v -m 0 /dev/ram0 2048
# mount -t ext2 /dev/ram0 /mnt
W ten sposób stworzyłeś 2MB wolumen ramdisk-u i zamontowałeś do w
/mnt
.
Krótkie ostrzeżenie: jeżeli używasz kerneld
(lub zastępującego go
kmod
w jądrach 2.2.x i późnych 2.1.x) w celu automatycznego ładowania i
odładowywania modułów, nie odmontowuj ramdisk-u dopóki nie skopiujesz
wszystkich plików na bardziej trwały nośnik. W chwili, gdy go odmontujesz,
kerneld
zakłada, że może odładować moduł (zwykle jednak czeka pewien
okres). Gdy to już się stanie, pamięć zostanie użyta przez inne części jądra
i stracisz wszystkie godziny spędzone na odzyskiwaniu danych.
Jeżeli masz napęd Zip, Jaz, LS-120 lub coś podobnego, może on spełniać z powodzeniem rolę partycji ratunkowej. W pozostałych przypadkach, użyj po prostu napędu stacji dyskietek.
Będziesz jeszcze potrzebował programu, który potrafi czytać dane ze środka
partycji. Właściwie może to zrobić dd
, ale aby przeczytać dane leżące
od 600 MB do 800 MB, dd
musi przeczytać i zignorować pierwsze 600 MB.
Zajmuje to dosyć dużo czasu, nawet na szybkich dyskach. Moim sposobem na
obejście tego problemu było napisanie programu, który przeskakuje w środek
partycji. Nazywa się on fsgrab
; pakiet ze źródłem możesz znaleźć na
mojej stronie domowej
lub na
Metalab-ie
(i kopiach, w Polsce -
Sunsite
). Jeśli będziesz chciał stosować tę metodę, w dalszej części tego
mini-JTZ zakładam, że masz fsgrab
.
Nie potrzebujesz fsgrab-a
, jeżeli żaden z plików, które starasz się
odzyskać, nie zajmuje więcej niż 12 bloków (przeważnie blok ma rozmiar jednego
kilobajta).
Jeżeli musisz użyć fsgrab-a
, ale nie chce Ci się go ściągać i kompilować,
jest też prosta droga na przetłumaczenie polecenia dla fsgrab
na
polecenie dla dd
. Mając
fsgrab -c count -s skip device
możesz użyć komendy dd
(przeważnie jest to dużo wolniejsze)
dd bs=1k if=device count=count skip=skip
Muszę Cię ostrzec, że chociaż dla mnie fsgrab
działa doskonale, nie
mogę brać odpowiedzialności za jego funkcjonowanie. Pisałem go dosyś szybko i
niestarannie, po prostu, aby działał poprawnie. Więcej szczegółów o
gwarancji znajdziesz w rozdziale `No Warranty' w pliku COPYING
dołaczonym do pakietu (the GNU General Public Licence).
Następnym krokiem jest odnalezienie w systemie plików tych iwęzłów,
które zostały ostanio uwolnione. Do tego zadania użyjemy programu
debugfs
. Uruchom debugfs
z nazwą urządzenia, na którym
przechowywany jest system plików:
# debugfs /dev/hda5
Jeżeli chcesz bezpośrednio wprowadzać zmiany do iwęzłów, dodaj opcję
-w
, aby umożliwić zapisywanie do systemu plików:
# debugfs -w /dev/hda5
lsdel
jest poleceniem debugfs
, które wyszukuje skasowane iwęzły. Po
zachęcie programu, napisz więc:
debugfs: lsdel
Po chwili świergotania dysku, długa lista zostanie przekierowana do Twojego
ulubionego łamacza na strony (ang. pager) (wartość zmiennej
$PAGER
). Powinienneś zachować gdzieś kopię tej listy.
Jeżeli używasz less
, możesz po prostu napisać -o
i nazwę pliku
wyjściowego. W innym razie, będziesz musiał przesłać wyniki do pliku w inny
sposób. Spróbuj czegoś takiego:
debugfs: quit
# echo lsdel | debugfs /dev/hda5 > lsdel.out
Teraz, tylko na podstawie czasu skasowania, rozmiaru, praw własności i właściciela musisz określić, które iwęzły należały do skasowanych plików. Będzie to prawdopodobnie proste zadanie jeśli wypadek przydarzył się 5 minut temu, jeśli nie, przeszukaj listę bardzo uważnie.
Polecam wydrukowanie sobie listy iwęzłów, które chcesz odzyskać. Ułatwi Ci to dalszą pracę.
debugfs
dysponuje poleceniem stat
, które wyświetla szczegółowe
informacje o iwęźle. Wykonaj tę komendę dla wszystkich iwęzłów, które chcesz
odzyskać. Na przykład, jeżeli interesuje Cię iwęzeł o numerze 148003, napisz
tak:
debugfs: stat <148003>
Inode: 148003 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 503 Group: 100 Size: 6065
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 12
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
594810 594811 594814 594815 594816 594817
TOTAL: 6
Gdy chcesz odzyskać wiele plików, dobrze będzie jak zautomatyzujesz ten
proces. Przy założeniu, że Twoja lsdel
lista interesujących iwęzłów
znajduje się w pliku lsdel.out
, napisz coś takiego:
# cut -c1-6 lsdel.out | grep "[0-9]" | tr -d " " > inodes
Nowy plik inodes
zawiera tylko numery iwęzłówm, które chcesz odzyskać,
po jednym w jednej linii. Zapisaliśmy to, bowiem później bardzo nam się
przyda. Potem piszesz po prostu:
# sed 's/^.*$/stat <\0>/' inodes | debugfs /dev/hda5 > stats
i plik stats
zawiera wyniki wszystkich poleceń stat
.
Ta część jest albo bardzo łatwa, albo trudna, w zależności od tego, czy plik który chcesz odzyskać zajmował więcej niż 12 bloków.
Jeżeli plik ma mniej niż 12 bloków, numery wszystkich bloków, które on
zajmuje zapisane są w jednym iwęźle. Możesz odczytać je po wykonaniu
polecenie stat
dla tego iwęzła. Ponadto, w debugfs
jest polecenie,
które automatycznie odzyskuje taki plik. Weźmy ten sam przykład co poprzednio:
debugfs: stat <148003>
Inode: 148003 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 503 Group: 100 Size: 6065
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 12
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
594810 594811 594814 594815 594816 594817
TOTAL: 6
Plik ten zajmuje sześć bloków. Ponieważ jest to mniej niż 12, możemy użyć
debugfs
, aby zapisać plik w nowym miejscu, na przykład
/mnt/recovered.000
:
debugfs: dump <148003> /mnt/recovered.000
Oczywiście można to zrobić również, posługując się fsgrab
. Pokażę jak
wygląda takie przykładowe wywołanie:
# fsgrab -c 2 -s 594810 /dev/hda5 > /mnt/recovered.000
# fsgrab -c 4 -s 594814 /dev/hda5 >> /mnt/recovered.000
Zarówno przy korzystaniu z debugfs
jak i fsgrab
, na końcu pliku
/mnt/recovered.000
pozostaną śmieci. Nie ma to większego znaczenia.
Łatwo można się ich pozbyć. Najprostszą metodą jest odczytanie pola
Size
w iwęźle i wpisanie tej wartości za opcją bs
komendy dd
:
# dd count=1 if=/mnt/recovered.000 of=/mnt/resized.000 bs=6065
Może się okazać, że jeden lub więcej z bloków zostało straconych, bowiem zostały już nadpisane. Jeżeli tak będzie, po prostu nie miałeś szczęścia: bloki te odeszły już na zawsze. (Wybraź sobie, że odmontowałeś je wcześniej!)
Problem pojawia się, gdy plik zajmuje więcej niż 12 bloków danych. Przypadek ten wymaga pewnej wiedzy o tym jak zbudowany jest system plików UNIX-a. Dane pliku przechowywane są w jednostkach zwanych `blokami'. Bloki te są numerowane sekwencyjnie. Każdy plik ma również `iwęzeł', w którym przechowywane są informacje typu: właściciel, prawa dostępu i typ. Podobnie jak bloki, iwęzły są numerowane sekwencyjnie, chociaż mają one różne numeracje. Pozycja w katalogu odpowiadająca plikowi składa się z jego nazwy i numeru iwęzła.
Jednak na postawie tych informacji jądro nie jest jeszcze w stanie odnaleźć na partycji danych odpowiadających jednej z pozycji w katalogu. Żeby to umożliwić, iwęzeł przechowuje położenia bloków danych zajmowanych przez plik. Zorganizowane jest to w następujący sposób:
Przeczytaj to jeszcze raz: wiem, że to jest skomplikowane, ale bardzo ważne.
Niestety wszystkie implementacje jądra, aż do wersji 2.0.36 podczas kasowania pliku zerują bloki pośrednie (podwójnie pośrednie, itd.). Jeśli Twój plik jest większy niż 12 bloków, nie masz gawarancji, że będzie możliwe odnalezienie numerów wszystkich jego bloków, nie mówiąc już nic o ich zawartości.
Jedyną metodą jaką udało mi się znaleźć, jest oparcie się na założeniu, że plik nie był pofragmentowany. Jeżeli był, masz poważny problem. Zakładając, że plik nie był pofragmentowany, istnieje kilka sekcji bloków danych, w zależności od tego ile bloków danych zajmuje plik:
Numery bloków przechowywane są w iwęźle, jak to było opisane wcześniej.
Po blokach bezpośrednich, odlicz jeden na blok pośredni, dalej znajduje się 256 bloków danych.
Tak jak poprzednio jest: 12 bezpośrednich bloków, (nieprzydatny) blok pośredni i 256 bloków. Po tym wszystkim następuje (nieprzydatny) podwójnie pośredni blok oraz 256 powtórzeń jednego (nieprzydatnego) bloku pośredniego i 256 bloków danych.
Położenie piewszych 65804 bloków jak wyżej. Potem potrójnie pośredni blok i 256 powtórzeń `sekwecji podwójnie pośredniej'. Każda podwójnie pośrednia sekwencja zawiera (nieprzydatny) podwójnie pośredni blok, po którym następuje 256 powtórzeń jednego (nieprzydatnego) bloku pośredniego i 256 bloków danych.
Oczywiście, nawet jeśli numery bloków, które przyjęliśmy, są poprawne, nie ma żadnych gwarancji, że dane są w nich są nienaruszone. Dodatkowo, im dłuższy był plik, tym mniejsze szanse, że system operacyjny zapisał go bez żadnej fragmentacji (za wyjątkiem wyjątkowych sytuacji).
Założyłem, że rozmiar Twoich bloków wynosi 1024 bajty, tyle ile wartość standardowa. Jeśli Twój blok jest większy, niektóre z liczb podanych wyżej zmienią się. Sprecyzujmy: dopóki numer każdego bloku ma długość 4 bajtów, rozmiarbloku/4 jest liczbą numerów bloków, które mogą być przechowane w każdym bloku pośrednim. Każde wystąpienie liczby 256 we wcześniejszym opisie, zastąp na rozmiarbloku/4. Zmianie ulegną również ograniczenia na ilość wymaganych bloków.
Popatrz na przykładowe odzyskiwanie dużego pliku.
debugfs: stat <1387>
Inode: 148004 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 503 Group: 100 Size: 1851347
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 3616
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8583
TOTAL: 14
Wydaje się, że mamy pewne szanse, że plik nie jest pofragmentowany. Pewne jest tylko, że pierwsze 12 bloków, których numery są zawarte w iwęźle, jest `po kolei'. Możemy więc odtworzyć te bloki:
# fsgrab -c 12 -s 8314 /dev/hda5 > /mnt/recovered.001
Następny blok, wymieniony w iwęźle, 8326, jest blokiem pośrednim, który ignorujemy. Mamy jednak nadzieję, że nastepne 256 bloków jest naszymi blokami danych (numery 8327 do 8582).
# fsgrab -c 256 -s 8327 /dev/hda5 >> /mnt/recovered.001
Ostatnim blokiem wymienionym w iwęźle jest 8583. Nadal zakładamy, że istnieje ciągłość w blokach. Jest to jednak uzasadnione bowiem: ostatnim blokiem danych był blok o numerze 8582 (8327 + 255). Blok 8583 jest podwójnie pośredni i może być zignorowany. Teraz może nastąpić do 256 powtórzeń bloku pośredniego (który można pominąć) i 256 bloków danych. Trochę arytmetyki i już można pisać kolejne polecenie. Zauważ, że pominęliśmy podwójnie pośredni blok 8583 oraz pośredni blok 8584 i rozpoczęliśmy czytać dane od bloku numer 8585.
# fsgrab -c 256 -s 8585 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 8842 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9099 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9356 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9613 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9870 /dev/hda5 >> /mnt/recovered.001
Dodajmy to wszystko, zapisaliśmy do tej pory 12 + (7 * 256) bloków, co daje 1804. Wyniki polecenia `stat' dla iwęzła dały nam `blockcount' (liczba bloków) równe 3616. Niestety są to bloki o rozmiarze 512 bajtów (zaszłość z UNIX-a), na prawdę potrzebujemy więc 3616/2 = 1808 bloków o rozmiarze 1024 bajty. Oznacza to, że musimy jeszcze odnaleźć cztery bloki. Ostatni przeczytany blok danych miał numer 10125. Tak jak to robiliśmy do tej pory, pomijamy blok pośredni (numer 10126) i możemy już zapisać ostatnie cztery bloki.
# fsgrab -c 4 -s 10127 /dev/hda5 >> /mnt/recovered.001
Przy pewnym szczęściu udało nam się odzyskać cały plik.
Metoda ta jest dużo prostsza. Jednak, tak jak wspomniałem wcześniej, nie może być jeszcze stosowana do plików większych niż 12 bloków.
W każdym iwęźle, który chcesz odzyskać musisz ustawić licznik podłączeń
(linkcount) na jeden i czas skasowania (deletion time) na zero. Robi się to
za pomocą polecenia mi
(modify inode) w debugfs
. Przykładowe
wywołanie, modyfikacja iwęzła 148003 (tego co wcześniej):
debugfs: mi <148003>
Mode [0100644]
User ID [503]
Group ID [100]
Size [6065]
Creation time [833201524]
Modification time [832708049]
Access time [826012887]
Deletion time [833201524] 0
Link count [0] 1
Block count [12]
File flags [0x0]
Reserved1 [0]
File acl [0]
Directory acl [0]
Fragment address [0]
Fragment number [0]
Fragment size [0]
Direct Block #0 [594810]
Direct Block #1 [594811]
Direct Block #2 [594814]
Direct Block #3 [594815]
Direct Block #4 [594816]
Direct Block #5 [594817]
Direct Block #6 [0]
Direct Block #7 [0]
Direct Block #8 [0]
Direct Block #9 [0]
Direct Block #10 [0]
Direct Block #11 [0]
Indirect Block [0]
Double Indirect Block [0]
Triple Indirect Block [0]
Ustawiłem czas skasowania na 0, licznik podłączeń na 1 i nacisnąłem Enter dla wszystkich innych pól. Jest to pewną niedogodnością, jeżeli masz wiele plików do odzyskania. Myślę jednak, że można z tym żyć. Jeśli oczekujesz wygody, lepiej zacznij używać graficznego `systemu operacyjnego' ze ślicznym `Koszem na śmieci'.
Przy okazji: polecenie mi
pokazuje `Czas stworzenia' (Creation
time) w iwęźle. To kłamstwo ! (lub, jak kto woli, pomyłka.) Prawda jest taka,
że nie można w systemie plików UNIX-a stwierdzić kiedy dany plik został
utworzony. Pole st_ctime
w struct stat
zawiera `czas zmiany
iwęzła', czyli czas ostaniej zmiany, któregoś z parametrów iwęzła. To tyle
z dzisiejszej lekcji.
Nowsze wersje debugfs
niż moja, prawdopodobnie nie wyświetalają
niektórych pól w iwęźle (szczególnie, Reserved1
i Fragment
).
Po zmianie w iwęzłach, możesz wyjść z debugfs
i napisać:
# e2fsck -f /dev/hda5
Pomysł polega na tym, że każdy ze skasowanych plików został odkasowany, ale
nie pojawił się w żadnym katalogu. Program e2fsck
umie to wykryć i
doda pozycję dla każdego z nich w katalogu /lost+found
systemu
plików. (Jeżeli partycja była zamontowana w /usr
, pliki pojawią się
w /usr/lost+found
, gdy ją zamontujesz.) Pracą, którą musisz jeszcze
zrobić, to nadanie plikom nazw i umieszczenie ich we właściwym miejscu
drzewa plików.
Po uruchomieniu e2fsck
, wyświetli Ci on trochę informacji, ale zada
również pytania, które zniszczenia naprawiać. Odpowiadaj `yes' (tak) na
wszystko co dotyczy `summary information' lub iwęzłów, które zmieniałeś.
Resztę pozostawiam do Twojej decyzji, pamiętaj, że nie jest najlepszą
metodą odpowiadanie `tak' na wszystkie pytania. Po skończeniu pracy
przez e2fsck
, możesz ponownie zamontować system plików.
Istnieje alternatywne rozwiązanie do pozwolenia, aby e2fsck
utworzył
pliki w /lost+found
. Możesz użyć debugfs
i stworzyć w systemie
plików dołączenie (link) do iwęzła. Służy do tego polecenie link
w
debugfs
, po zmianach w samym iwęźle:
debugfs: link <148003> foo.txt
W ten sposób powstanie w bieżącym katalogu plik o nazwie foo.txt
;
foo.txt
będzie Twoim odzyskanym plikiem. Nadal musisz jednak uruchomić
e2fsck
, aby uaktualnić informacje ogólne, liczniki bloków itp. itd.
Tak. Właściwie, mam nadzieję, że tak. Chociaż, gdy to piszę, aktualna, stabilna wersja jądra (seria 2.0.x) zeruje bloki pośrednie. Wersje serii rozwojowej 2.1.x i stabilnej 2.2.x nie mają tej wady. Dzisiaj, 2 lutego 1999 minęło dopiero kilka dni od wydania jądra 2.2.1; prawdopodobnie pojawi się ono w dystrybucjach za jeden, dwa miesiące.
Kiedy wersje jądra rozwiążą problem zerowania bloków pośrednich, wiele moich
ręcznych technik modyfikacji iwęzłów nie będzie już potrzebnych. W tym
samym czasie stanie się możliwe użycie polecenia dump
w debugfs
dla dużych plików i innych programów narzędziowych do odzyskiwania plików.
Pewnie, że są. Niestety cierpią one na te same problemy co ręczna technika zmian w iwęzłach: bloki pośrednie są nieodzyskiwalne. Warto im się przyjrzeć, bowiem wydaje się, że ograniczenie to wkrótce zniknie.
Napisałem program e2recover
, który jest właściwie tylko Perl-ową
otoczką dookoła fsgrab
. Stara się on poradzić sobie z wyzerowanymi
blokami pośrednimi i wydaje sie, że działa całkiem nieźle dla dużych plików,
które nie uległy fragmentacji. Ustawia poprawne prawa dostępu (i właściciela,
gdy to jest możliwe). Upewnia się również, że odzyskiwany plik ma poprawny
rozmiar.
Program e2recover
był planowany jako część poważnych zmian w tym Howto;
oznacza to niestety, że więcej użytecznej dokumentacji do e2recover
będzie zamieszczone dopiero w nowej wersji tego dokumentu. Jednak i teraz
może on się komuś przydać; można go ściągnąć z
mojej strony domowej, i wkrótce z Metalab-a (jest już w Polsce -
Sunsite).
Scott D. Heavner jest autorem programu lde
, the Linux Disk Editor.
Może on być używany zarówno jako binarny edytor dysku i jako odpowiednik
debugfs
dla systemów plików ext2 i minix, a nawet dla systemu plików
xia (chociaż wsparcie dla xia przestało być dostępne w jądrach 2.1.x i 2.2.x).
Zawarto w nim kilka pomysłów wspomagających odzyskiwanie skasowanych plików:
śledzenie listy bloków tworzących plik i wyszukiwanie danych na dysku. Zawiera
on także całkiem użyteczną dokumentację o podstawach systemu plików oraz jak go
używać do odzyskiwania plików skasowanych. Wersja 2.4 lde
jest dostępna na
Metalab-ie (i kopiach, w Polsce -
Sunsite), lub na
stronie domowej autora.
Inne możliwości oferowane są przez GNU Midnight Commander, mc
. Jest to
pełnoekranowe narzędzie do zarządzania plikami, oparte na znanym w
środowisku MS-DOS programie o nazwie `NC'. mc
obsługuje mysz zarówno
na konsoli, jak i w oknie xterm-a, dostarcza mechanizm wirtualnych systemów
plików, co umożliwia triki takie jak cd
do archiwum tar. Odzyskiwanie
plików obsługiwane jest przez jeden z takich wirtualnych systemów plików.
Wszystko to brzmi bardzo zachęcająco, ale muszę przyznać, że nie używam
tego programu -- wolę staromodne polecenia powłoki.
Aby używać możliwości odzyskiwania skasowanych plików, musisz skonfigurować
program z opcją -
-with-ext2undel
; będziesz również potrzebował
bibliotek w wersji rozwojowej i niektórych plików zawartych w pakiecie
e2fsprogs
. W ten sposób zbudowana jest wersja dostarczana w
Debian GNU/Linux; tak samo może
być w innych dystrybucjach. Teraz możesz po prostu kazać mu cd
undel:/dev/hda5
, i otrzymasz `zawartość katalogu' ze skasowanymi
plikami. Jak wiele innych i ten program bardzo źle radzi sobie z zerowaniem
bloków pośrednich -- przeważnie odtwarza tylko pierwsze 12k większych
plików.
Aktualną wersję można ściągnąć z serwera ftp the Midnight Commander.
Mam zamiar regularnie uaktualniać ten dokument tak długo jak będę miał
wystarczająco dużo czasu i coś ciekawego do powiedzenia. Oznacza to, że bardzo
mi zależy na komentarzach od czytelników. Czy moje pisanie może być
bardziej zrozumiałe? Czy myślicie o czymś, co uczyniłoby problem prostszym?
Jest jakiś program, który robi to wszystko automatycznie? Jeżeli masz coś do
powiedzenia o tym dokumencie, albo o fsgrab
, albo o e2recover
,
napisz do mnie
aaronc@pobox.com
.
`Jeżeli widzę dalej od innych, to dlatego, że stoję na ramionach olbrzymów.' (Isaac Newton)
To mini-Howto wywodzi się z listu zamieszczonego w grupie
comp.os.linux.misc
przez Robina Glovera
swrglovr@met.rdg.ac.uk
.
Chciałbym podziekować Robinowi za wspaniałomyślne pozwolenie na
przetworzenie jego pomysłów w to mini-Howto.
Korzystając z okazji, chciałbym jeszcze raz podziękować wszystkim, którzy napisali do mnie o tym Howto. Otrzymywanie wyrazów wdzieczności czyni pracę wartą wysiłku.
Niektóre odnośniki bibliograficzne:
Wszystkie znaki towarowe są własnością ich prawowitych właścicieli. Konkretnie:
Prawa autorskie do tego dokumentu 1997, 1999 posiada Aaron Crane
aaronc@pobox.com
.
Może on być darmowo rozpowszechniany w całości, łącznie z tą notą autorską.
Nie może być zmieniany bez zgody autora lub koordynatora Linux
Documentation Project HOWTO. Nie dotyczy to tylko kopiowania jego części w
celu przeglądania lub cytowania; w takim przypadku, części te muszą być
poprawnymi cytatami i nie muszą zawierać noty o prawach autorskich.
Autor oczekuje, ale nie wymaga, że ten kto będzie chciał sprzedawać kopie tego dokumentu, niezależnie od tego, czy na nośniku elektronicznym, czy papierowym, poinformuje jego lub koordynatora projektu Linux HOWTO o swoich zamiarach.
Koordynatorem projektu Linux HOWTO jest aktulanie Tim Bynum
linux-howto@sunsite.unc.edu
.
Starałem się, aby tłumaczenie było najwierniejsze z możliwych. Dlatego nie ma żadnych zmian w stosunku do orginału, za wyjątkiem odnośników do polskiej kopii serwera Metalab na Sunsite.icm.edu.pl.
Czekam na komentarze pod adresem: Bartosz Sawicki
sawickib@ee.pw.edu.pl
.