檔案刪除的回復救援

今天幹了件很蠢的事情~.. 想要將 a電影.srt 改成跟 電影.avi 同名字.
於是就下了 mv a電影.srt 電影.avi ... 當按下 enter 時清醒了過來...
發現到那 avi 已經被我清掉了.. 變 srt 了... :~
於是就有這篇文章的由來.... 嗚... :~
雖然是寫說檔案刪除的回復救援, 但事實上我沒有成功救回來.. XD
主要是因為還要 mount -ro 而且我砍的檔案是在 "/". 很麻煩~ 🙁
而且也並不是那麼重要的檔案~ 大不了就那影片別看罷了... :p
但是看了這麼多~ 來做點小筆記比較好.. 希望未來不會需要用到這篇...


先簡單看一下幾種常用的 filesystem - Linux日誌式文件系统面面觀
(這篇下面有許多相關文件蠻不錯的)


重點摘要:
主要是下面這三篇文章. 若已經是死連結. 就參考下面轉載回來的吧~ 🙂
說明系統rm, mv 等等動作是做何種事情, 流程, 該如何救回來 - UNIX系统被删文件的恢复策略
簡易說明實作步驟: Linux檔系統的反刪除方法
實作搶救的心得:[chat] 搶救過去!!!! (ext2 undelete)
救援主要就是靠 debugfs 這個程式.
debugfs 的程式就兩個 file, 大約共 500 行. 有興趣的就於下處去看看吧~(kernel 2.6.11)
/usr/src/linux/fs/debugfs/


以下都是轉載自原網站, 怕原網站資料遺失就頭痛了~ 🙁


下面這兩篇事實上是一樣的, 不過怕資料會遺失. 先記起來~ 🙂
[chat] 搶救過去!!!! (ext2 undelete)
ext2文件系统下恢复误删除的文件
轉載上述連結:
發信人: thhsieh (居士), 信區: SM
標 題: [Sys] 搶救過去!!!! (ext2 undelete)
發信站: 冷月流蘇BBS驛站 (Mon Feb 1 17:21:11 1999) , 轉信
本系的 BBS 系統真是多災多難 (嗯 .... 其實是因為我的疏忽,才會這麼多災
多難 ....) ,繼這幾日系統時間不正確,造成許多人的 ID 被誤砍後,又一次
因系統設定上的問題,將 BBS 的重要備份檔給殺了。這件事是學弟發現後告訴
我的,當我上站來一見到他的 mail, 當真是欲哭無淚,差點沒去撞牆。那個備
分檔有多重要呢? 這麼說吧! 所有等待我們恢復舊信件的使用者資料全在裏頭。
那時已是週六晚 11:00 左右,我一邊想著要編一套說辭向大家解釋無法替大家
恢復舊信件與設定了,一邊還在想是否能夠挽回局面。大家知道, UNIX like
的系統是很難像 M$ 的系統一樣,做到 undelete 的,所有網管前輩都曾再三
警告我們,要小心! 小心! 砍檔之前三思而後行,砍了之後再後悔也沒用。雖
然我已漸漸做到砍檔三思而後行,但之次誤砍事件是系統在背景中定時執行的,
等到我找出原因時已是檔案被砍後一個多小時。
我憑著一點點的印象,想起在網路上,有人討論過在 Linux ext2 filesystem
中 undelete 的可能性,但我所見到的多半是負面的答案,但好像真的有人做過
這件事,於是我第一個所做的,就是馬上將該檔案原來所在的 partition mount
成 read-only, 禁止任何的寫入動作,不是怕再有檔案被誤砍 (因為已沒什麼可
砍的了) ,而是怕有新檔案寫進來,新資料可能會覆蓋到舊資料原本存在的磁區
(block) 。我們現在唯一個指望,就是企圖將檔案原來存在的磁區一個個找回來,
並且「希望」這些磁區上的舊資料都還在,然後將這些磁區串成一個檔案。
終於被我找到了!! 原來這方面的技術文件就存在我自己的系統中 :-))
/usr/doc/HOWTO/mini/Ext2fs-Undeletion.gz
於是我就按照這份文件的指示一步步來,總算將一個長達 8MB 的壓縮檔救回了
99%, 還有一個長達 1.1 MB 的壓縮檔完整無缺地救了回來。感謝上帝、 Linux
的設計者、寫那篇文件的作者、曾經討論過此技術的人、以及 Linux 如此優秀
的 ext2 filesystem, 讓我有機會搶救過去。現在,我將我的搶救步驟做一個整
理讓大家參考,希望有派得上用場的時候 (喔! 不,最好是希望大家永遠不要有
機會用到以下的步數 :-)))
************************************************************************
在此嚴正聲明!! 寫這篇文章的目的,是給那些處於萬不得已情況下的人們,有
一個挽回的機會,並不意味著從此我們就可以大意,砍檔不需要三思。前面提
到,我有一個檔案無法 100% 救回,事實上,長達 8MB 的檔案能救回 99% 已是
幸運中的幸運,一般的情況下若能救回 70% - 80% 已經要愉笑了。所以,不要
指望 undelete 能救回一切。預防勝於治療! 請大家平時就養成好習慣,砍檔前
請三思!!!
************************************************************************
我們能救回的機會有多大? 在 kernel-2.0.X 系列中 (本站所用的 kernel 是
2.0.33) ,取決以下兩點:
1. 檔案原來所在的磁區是否沒有被覆寫?
2. 檔案是否完全連續?
第一點我們可以與時間競賽,就是當一發現檔案誤砍時,要以最快的速度 umount
該 filesystem, 或將該 filesystem remount 成唯讀。就這次的情況而言,檔案
誤砍是在事發一個小時後才發現的,但由於該 filesystem 寫入的機會很少 (我
幾乎可確定一天才只有一次,做 backup),所以第一點算是過關了。
第二點真的是要聽天由命了,就本站所使用的 kernel, 必須要在假設「長檔案」所
佔的 block 完全連續的情況下,才有可能完全救回來! 一個 block 是 1024 bytes,
長達 8 MB 的檔案就有超過 8000 個 block。在經常讀寫的 filesystem 中,可以
想見長檔案很難完全連續,但在我們的系統中,這一點似乎又多了幾分指望。同時,
Linux ext2 如此精良的 filesystem, 能做到前 7950 多個 block 都連續,這一點
也功不可沒。
好了,以下我就講一下我的步驟。
1. mount filesystem readonly:
該檔案的位置原來是在 /var/hda/backup/home/bbs 下,我們系統的 filesystem
組態是:
root@bbs:/home/ftp/rescue# df
Filesystem 1024-blocks Used Available Capacity Mounted on
/dev/sda1 396500 312769 63250 83% /
/dev/sda3 777410 537633 199615 73% /home
/dev/hda1 199047 36927 151840 20% /var/hda
/dev/hda2 1029023 490998 485710 50% /home/ftp
因此 /var/hda 這個 filesystem 要馬上 mount 成 readonly (以下請用 root 身
份):
mount -o remount,ro /var/hda
當然也可以直接 umount 它,但有時候可能有某些 process 正在此 filesystem
下運作,您可能無法直接 umount 它。因此我選擇 mount readonly。但您也可以
用:
fuser -v -m /usr
看一下目前是那些 process 在用這個 filesystem, 然後一一砍掉,再 umount。
2. 執行
echo lsdel | debugfs /dev/hda1 | less
看一下該 filesystem 最近被砍的 inode (檔案) 有那些 (為什麼是 /dev/hda1?
請見上頭的 df 列表)? 在這裏要說一下,在 UNIX like 的系統中,所有的檔案都
有一個 inode 指向它, inode 中記錄了檔案的重要資訊,如大小、時間、屬性等
等。就我們的系統而言,其列示如下:
debugfs: 92 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
.................................................................
29771 0 100644 1255337 14/ 14 Sat Jan 30 22:37:10 1999
29772 0 100644 5161017 14/ 14 Sat Jan 30 22:37:10 1999
29773 0 100644 8220922 14/ 14 Sat Jan 30 22:37:10 1999
29774 0 100644 5431 6/ 6 Sat Jan 30 22:37:10 1999
請注意! inode 裏頭不會記錄檔案的檔名,檔名是記錄在該檔案所在的目錄的
data block 中,故在此我們見不到。因此,我們必須要在檔案大小、被砍時間
等資訊中判斷出要救回的檔案是那一個。在此,我們要救回 29773 這個 inode。
3. 執行
echo "stat <29773>" | debugfs /dev/hda1
列出該 inode 的所有資訊,如下:
debugfs: stat <29773>
Inode: 29773 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 0 Group: 0 Size: 8220922
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 16124
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x36b31916 -- Sat Jan 30 22:37:10 1999
atime: 0x36aebee4 -- Wed Jan 27 15:23:16 1999
mtime: 0x36adec25 -- Wed Jan 27 00:24:05 1999
dtime: 0x36b31916 -- Sat Jan 30 22:37:10 1999
BLOCKS:
123134 123136 123137 123138 123140 131404 131405 131406 131407 131408 131409 131
410 131411 131668
TOTAL: 14
現在的重點是,必須將該 inode 所指的檔案,所指的 block 全部找回來。在這裏,
列出的資訊顯示只有 14 個 block? 不對啊! 應該要有 8000 多個 block 才對啊!
在這裏要談一下 UNIX like filesystem 的「奧密」了。上頭所列的前 12 個 block
是真正指到檔案資料的 block, 稱之為 direct block 。第 13 個稱為第一階
indirect block, 第 14 個稱為第二階 indirect block 。什麼意思? 該檔的資料
所在的 block 位置如下:
123134
123136
123137
123138
......
131409
131410
131411 =========> 131412
131413
131414 (第一階,共 256 個)
......
131667
131668 =========> 131669 ==========> 131670
131671
131672 (共 256 個)
......
131925
131926 ==========> 131927
131928
131929 (共 256 個)
......
132182
132183 ==========> 132184
132185 (共 256 個)
......
各位明白嗎? 第 13 個 (131411) 與第 14 個 block 其實不是 data, 而是 index,
它指出接下來的 block 的位置。由於一個 block 的大小是 1024 bytes, 一個 int
在 32 位元系統中是 4 bytes, 故一個 block 可以記錄 256 筆資料。以 131411
block 為例,它所記錄的資料即為 (在檔案未砍前):
131412 131413 131414 .... 131667 (共 256 筆)
而這 256 個 block 就真正記錄了檔案資料,所以我們稱為第一階。同理,第二階
就有兩個層 index, 以 131668 來說,它可能記錄了:
131669 131926 132182 .... (最多有 256 筆)
而 131669 的 block 記錄為:
131670 131671 131672 .... 131925 (共 256 筆)
而這 256 個 block 才是真正儲存檔案資料的。而我們要的,就是這些真正儲存檔
案資料的 block 。
理論上,我們只要將這些 index block 的內容全部讀出來,然後照這些 index 把
所有的 block 全部讀到手,就能 100% 救回檔案 (假設這些 block 全部沒有被新
檔案覆寫的話)。工程很大,但是可行。不幸的是,在 kernel-2.0.33, 其設計是,
如果該檔案被砍了,則這些 index block 全部會規零,因此我所讀到的是
0 0 0 0 0 ..... (共 256 筆)
哇! 沒辦法知道這些 data block 真正所在的位置。所以,在此我們做了一個很大
的假設: 整個檔案所在的 block 是連續的! 也就是我上頭的例子。這也就是為什
麼說,只有連續 block (是指後頭的 indirect block) 的檔案才能完整救回,而
這一點就要聽天由命了。
4. 好了,現在我們只好假設所有的檔案處於連續的 block 上,現在請用
http://archie.ncu.edu.tw
去找這個工具: fsgrab-1.2.tar.gz, 並將它安裝起來。因為步驟很簡單,故在此
我就不多談。我們要用它將所需的 block 全部抓出來。它的用法如下:
fsgrab -c count -s skip device
其中 count 是只要 (連續) 讀幾個, skip 是指要從第幾個開始讀,例如我要從
131670 開始連續讀 256 個,就這樣下指令:
fsgrab -c 256 -s 131670 /dev/hda1 > recover
現在我們就開始救檔案吧! 以上頭的資料,我們必須用以下的指令來救:
(注意到頭開的 12 個 block 並沒有完全連續!!!)
fsgrab -c 1 -s 123134 /dev/hda1 > recover
fsgrab -c 3 -s 123136 /dev/hda1 >> recover
fsgrab -c 1 -s 123140 /dev/hda1 >> recover
fsgrab -c 7 -s 131404 /dev/hda1 >> recover
這是開頭的 12 個 block, 對於第一階 indirect, 就資料來看好像是連續的 :-))
fsgrab -c 256 -s 131412 /dev/hda1 >> recover
注意要跳過 131411, 因為它是 index block。對於第二階 indirect, 我們 *假設*
它們都是連續的:
fsgrab -c 256 -s 131670 /dev/hda1 >> recover
fsgrab -c 256 -s 131927 /dev/hda1 >> recover
fsgrab -c 256 -s 132184 /dev/hda1 >> recover
............................................
要一直做,直到 recover 的大小超過我們所要救回的檔案大小 (8220922) 為止。
要注意在這裏我們已很小心地跳過那些 index block (如 131668, 131669, 131926,
132183, ....) 了。
5. 最後一步,就是把檔案「剪」出來,並看看我們救回多少了。在這裏我們可以用
split 這個工具,假設我們重覆上述步驟,弄出來的 recover 檔大小為 8294400,
而我們要的大小是 8220922, 那就這樣下指令:
split -b 8220922 recover rec
則會做出兩個檔,一個是 recaa, 大小是 8220922, 另一個是 recab 則是剩下的大
小,後者是垃圾,扔了即可。現在我們可以檢查這個檔案是不是「完整」的那個被
誤砍的檔案了。由於我們的那個檔案是 .tar.gz 的格式,於是我們這個方法來檢查:
mv recaa recaa.tar.gz
zcat recaa.tar.gz > recaa.tar
如果沒有錯誤訊息,那表示成功了! 完全救回來了。但不幸的是,我們沒有成功,
將弄出的 recaa.tar 改名再 gzip 之後,與原來的 recaa.tar.gz 比一下大小,發
現少了 1%, 表示說該檔原來所在的 block 中最後有 1% 是不連續的 (或者被新寫
入的檔案覆寫了),但這已是不幸中的大幸了。
=============================================================================
對於在 undelete 時 *必需* 假設所有 block 連續的問題,那份 HOWTO 文件說 Linus
與其他 kernel 設計者正著手研究,看能否克服這個困難,也就是在檔案砍掉時,不要
將 index block 規零。我剛剛試一下 kenrel-2.2.0 的環境,發現已做到了!! 以下是
一個已砍的檔案的 inode data (由 debugfs 所讀出):
debugfs: Inode: 36154 Type: regular Mode: 0600 Flags: 0x0 Version: 1
User: 0 Group: 0 Size: 2165945
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 4252
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x36b54c3b -- Mon Feb 1 14:39:55 1999
atime: 0x36b54c30 -- Mon Feb 1 14:39:44 1999
mtime: 0x36b54c30 -- Mon Feb 1 14:39:44 1999
dtime: 0x36b54c3b -- Mon Feb 1 14:39:55 1999
BLOCKS:
147740 147741 147742 147743 147744 147745 147746 147747 147748 147769 147770 157
642 157643 157644 157645 157646 157647 157648 157649 157650 157651 157652 157653
157654 157655 157656 157657 157658 157659 157660 157661 157662 157663 157664 15
7665 157666 157667 157668 157669 157670 157671 157672 157673 157674 157675 15767
6 157677 157678 157679 157680 157681 157682 157683 157684 157685 157686 157687 1
............................................................................
9745 159746 159747 159748 159749 159750 159751 159752 159753 159754 159755 15975
6
TOTAL: 2126
真是太完美了!! 這意味著在 kernel-2.2.X 的環境下,我們不必假設所有的 block 都
連續,而且可以百分之百找回所有砍掉的 block! 因此上述的第二個風險就不存在了。
以上資料,謹供參考。
參考文件: Ext2fs-Undeletion Mini HOWTO



UNIX系统被删文件的恢复策略
以下轉載自上述連結:
蓝森林 http://www.lslnet.com 2001年1月17日 20:19
作者: 李贵林 陈朝晖
与DOS/Windows不同,UNIX文件被删除后很难恢复,这是由UNIX独特的文件系统结构决定的。UNIX文件目录不像 DOS/Windows那样,文件即使被删除之后仍保存有完整的文件名、文件长度、始簇号(即文件占有的第一个磁盘块号)等重要信息;相反,它的文件信息全部依靠一种被称为i节点的数据结构来描述,而i节点在相应文件被删除之后即被清空,因此,要想直接恢复被删除的文件内容几乎是不可能的,必须另辟蹊径。本文结合实际,讨论几种文件恢复策略及其关键步骤的具体实现。
  一、UNIX文件系统结构
  我们知道,UNIX是以文件卷作为其文件系统存储格式的,而不同的UNIX系统,文件卷格式是有差异的,甚至即使是同一UNIX操作系统的不同版本,其文件系统未必完全相同,例如:SCO UNIX 4.1版与5.0版文件系统结构就有明显差异,但只要是UNIX系统,其文件卷的基本结构是一致的。分析如下:
  不管是什么UNIX系统,不管什么版本,其文件卷至少包括引导块、超级块、i节点表、数据区等几个部分。除此之外,不同UNIX版本可能还有不同的差异。例如:SCO UNIX系统的位图索引块和位图块AIX的逻辑卷表等。这些系统的特殊性不影响下文的恢复策略,故这里不作讨论,仅介绍标准UNIX文件卷结构。
 1. 引导块
  位于文件卷最开始的第一扇区,这512字节是文件系统的引导代码,为根文件系统所特有,其他文件系统这512字节为空。
  2. 超级块
  位于文件系统第二扇区,紧跟引导块之后,用于描述本文件系统的结构。如i节点长度、文件系统大小等,其结构存放于/usr/include/sys/filsys.h中,其结构如下:
  struct filsys
  {
  ushort s_isize; /*磁盘索引节点区所占用的数据块数*/
  daddr_t s_fsize; /*整个文件系统的数据块数*/
  short s_nfree; /*在空闲块登录表中当前登记的空闲块数目*/
  daddr_t s_free[NICFREE]; /*空闲块登记表*/
  short s_ninode; /*空闲索引节点数*/
  ino_t s_inode[NICINOD]; /*空闲节点登记表*/
  char s_flock; /*加锁标志位*/
  char s_ilock; /*节点加锁标志位*/
  char s_fmod; /*超级块修改标志*/
  char s_ronly; /*文件系统只读标志*/
  time_t s_time; /*超级块上次修改的时间*/
  short s_dinfo[4]; /*设备信息*/
  daddr_t s_tfree; /*空闲块总数*/
  ino_t s_tinode; /*空闲节点总数*/
  char s_fname[6]; /*文件系统名称*/
  char s_fpack[6];
  long s_fill[13]; /*填空位*/
  long s_magic; /*指示文件系统的幻数*/
  long s_type; /*新文件系统类型*/
  };
  3. i节点表
  i节点表存放在超级块之后,其长度是由超级块中的s_isize字段决定的,其作用是用来描述文件的属性、长度、属主、属组、数据块表等,其数据结构在/usr/include/sys/ino.h中,如下:
  struct dinode
  {
  ushort di_mode;
  short di_nlink;
  ushort di_uid;
  ushort di_gid;
  off_t di_size;
  char di_addr[40];
  time_t di_atime;
  time_t di_mtime;
  time_t di_ctime;
  };
  4. 目录结构
  UNIX所有文件均存放于目录中,目录本身也是一个文件。目录存放文件的机制如下:首先,目录文件本身也象普通文件一样,占用一个索引节点,其次,由这个索引节点得到目录内容的存放位置,再次,从其内容中取出一个个的文件名和它对应的节点号,从而访问一个文件。目录结构如下:
  索引节点号(2字节) .(本目录)(14字节)
  索引节点号(2字节) ..(父目录)(14字节)
  索引节点号(2字节) 文件名(14字节)
  索引节点号(2字节) 文件名(14字节)
  索引节点号(2字节) 文件名(14字节)
  由上可知文件名是依靠目录来描述的,文件的内容和其他信息则由索引节点来描述。
  二、文件的删除过程
  UNIX下删除一个文件的过程很简单,那就是释放索引节点表和文件占用的数据块,清空文件占用的索引节点,但不清除文件内容。但删除文件与删除目录的处理不尽相同,不同命令删除文件的过程也不相同。
  1. 删除一个文件
  UNIX 删除一个文件的具体步骤是:根据文件i节点的地址表逐一释放文件占用的磁盘数据块,然后清空相应的节点,最后释放i节点。
  2. 删除一个目录
  删除一个目录的过程:首先逐一删除目录里的所有文件,然后删除目录。目录本身也是一个文件,故删除方法与删除文件一致。
  3. 几种不同的删除命令
  .rm 命令
  一般删除命令,删除过程上述已说明。
  .mv命令
  格式:mv 文件1 文件2
  处理过程是将文件2的数据块释放,然后将文件1的名称改为文件2,再释放文件2所占的i节点。
  . > 命令
  格式:>文件名
  若产生一个新文件,>命令仅仅申请一个i节点,而不写入任何文件内容;若清空一个已经存在的文件,则释放文件所占的数据块,并将文件长度清零。
  三、被删文件的恢复策略
  要恢复被删除的文件,只能根据删除后留下的东西去做文章。文件被删除后留下了什么呢?由上述分析可知:其一、留下了文件的内容;其二、留下了“现场”。文件的恢复策略只能从这两个方面来分析。以下谈几种恢复策略。
  1.根据磁盘现场进行恢复
  如果文件被删除,现场未被破坏(即文件被删除后硬盘未发生过写操作),而且假定只删除了一个文件,那么可根据系统的分配算法进行恢复。因为系统建立一个文件时,必定根据某一特定的分配算法决定文件占用的数据块位置。而当该文件被删除后,它所占用的数据块被释放,又回到系统的分配表中,这时如果重新建立一个文件,系统根据原来的分配算法分配出的数据块必定跟该文件原来占用的数据块一致,而且我们知道,UNIX文件最后一数据块尾部多出的字节是全部置0的,据此只要调用系统的数据分配算法,在系统中一块块的申请数据块,因为UNIX文件最后一个数据块尾部多出的字节全部为0,所以,只要发现一个分配出的数据块中尾部全为0,即可认为文件结束,由此可确定文件长度和内容,进而实现恢复。方法如下:
  ⑴申请一个索引节点,即向系统申请创建一个新文件名而不写入任何内容。如:#>/tmp/xx
  ⑵调用系统分配数据块算法getnextfreeblock()得到一个数据块号,记入某一地址表变量中。
  ⑶读出这个数据块,判断其尾部是否全部连续为0,若不是,则回到(2),若是,则进行(4)。
  ⑷首先用系统函数fstat得到/tmp/xx的i节点号,然后将(2)步所得的地址表写入索引节点的地址表中(注意间址问题),并根据数据块个数和最后一块中有效数据长度计算出文件大小,写入i节点的di_size字段。
  ⑸回写系统的索引节点表即可。
  需要说明的是,第一,系统分配数据块的算法因不同的UNIX版本而不同;第二,有的UNIX如SCO UNIX 5.0版,其空闲数据块的分配和回收是使用一种动态链表的数据结构来实现的,它们的文件恢复更加容易,只要在空闲链表中的表尾去寻找即可,笔者另行描述。
  2. 根据内容恢复。
  若现场已被破坏,即硬盘发生过写操作,那么只好根据内容来恢复。而且,由于UNIX是一个多进程、多用户系统,它每一次开关机或硬件、通讯故障等都会记录系统日志、.sh_history等,硬盘现场被破坏可能性极大。因此讨论按内容恢复的方法具有更大的实用价值。笔者经过实际探索得出下列四种恢复策略供参考。
  ⑴关键字搜索法
  如果知道被删除的文件内容中若干字节的内容,而且该文件长度又不超过一个磁盘块,那么可以在整个文件系统中搜索这一字节串,得出一个文件所在的数据块,将它们的块号填入一个i节点,即可恢复一个文件,搜索文件系统的算法很简单,说明如下:
  a. #df -k 确定文件系统的设备文件名(如/dev/root)
  b.用下述函数搜索,若成功,返回数据块号,反之返回-1。其中fsname是文件系统的设备名,如/dev/root,comp()参数是实现搜索条件的函数。
  long searchfs(char *fsname , int comp())
  {
  FILE *fp;
  char buf[1024];
  long i=0;
  fp=fopen(fsname,"r");
  while (!feof(fp))
  {
  fread(buf,1024,1,fp);
  if (comp()) /* 检查是否符合搜索条件 */
  return i; /* 若成功返回块号 */
  i++;
  }
  fclose(fp);
  return -1; /* 未找到符合条件的块,返回-1*/
  }
  ⑵精确长度搜索法
  如果知道被删除文件的精确长度(字节数),那么可根据一个数据块的大小,计算出文件的最后一个数据块中数据的精确长度,该数据块中其他字节必然是全0。根据这一条件,通过搜索整个文件系统,找出其中符合条件的数据块,若出现多个块符合要求,则还需要根据其他条件区分。但不管怎样,根据精确长度分析也是恢复数据的一个策略。
  ⑶内容关联法
  如果知道文件内容中存在某种可实现的关联,例如文件的校验和,或者文件内容的某种上下文关系,那么也可通过搜索整个文件系统,通过反复尝试寻找符合关联条件的磁盘数据块,进而恢复一个文件。
  ⑷环境比较法
  如果知道删除文件所在的文件系统的安装过程,那么,另行找一台完全相的机器,按原来完全相同的步骤安装相同版本的UNIX和相应的其他软件,可以想象,新的机器环境会与原来的环境基本相同,比较两个机器上相同文件系统的内容,可以推断出被删除文件的大致位置,至少可以大大减少查找的范围,一旦查找的范围足够小时,可以用逐个观察和尝试的方法结合其他条件恢复数据,降低恢复的难度,增加恢复的可靠性。
  UNIX系统下文件系统恢复的具体实现依赖于不同操作系统和不同版本的具体文件系统结构和磁盘块分配算法。本文试图总结出一种一般性的思路和策略,限于篇幅,不能详细讨论它们的具体实现过程。
摘自:http://linux.softhouse.com.cn



Linux檔系統的反刪除方法
以下轉載自上述連結:
Linux檔系統的反刪除方法
  作為一個多用戶、多工的作業系統,Linux下的檔一旦被刪除,是難以恢復的。儘管刪除命令只是在檔節點中作刪除標記,並不真正清除檔內容,但是其他用戶和一些有寫盤動作的進程會很快覆蓋這些資料。不過,對於家庭單機使用的Linux,或者誤刪檔後及時補救,還是可以恢復的。
1.Ext2檔系統結構的簡單介紹
  在Linux所用的Ext2檔系統中,檔是以塊為單位存儲的,默認情況下每個塊的大小是1K,不同的塊以塊號區分。每個檔還有一個節點,節點中包含有檔所有者,讀寫許可權,檔類型等資訊。對於一個小於12個塊的檔,在節點中直接存儲檔資料塊的塊號。如果檔大於12個塊,那麼節點在12個塊號之後存儲一個間接塊的塊號,在這個間接塊號所對應的塊中,存儲有256個檔資料塊的塊號(Ext2fs中每個塊號佔用4位元組,這樣一個塊中所能存儲的塊號就是 1024/4=256)。如果有更大的檔,那麼還會在節點中出現二級間接塊和三級間接塊。
2。恢復被誤刪檔的方法
  大多數Linux發行版都提供一個debugfs工具,可以用來對Ext2檔系統進行編輯操作。不過在使用這個工具之前,還有一些工作要做。
  首先以唯讀方式重新掛載被誤刪的檔所在分區。使用如下命令:(假設文件在/usr分區)
mount –r –n –o remount /usr
-r表示唯讀方式掛載;-n表示不寫入/etc/mtab,如果是恢復/etc上的檔,就加上這個參數。如果系統說xxx partion busy,可以用fuser命令查看一下是哪些進程使用這個分區上的檔:
fuser –v –m /usr
如果沒有什麼重要的進程,用以下命令停掉它們:
fuser -k –v –m /usr
然後就可以重新掛載這些檔系統了。
  如果是把所有的檔統一安裝在一個大的/分區當中,可以在boot提示符下用linux single進入單用戶模式,儘量減少系統進程向硬碟寫入資料的機會,要不乾脆把硬碟掛在別的機器上。另外,恢復出來的資料不要寫到/上面,避免破壞那些有用的資料。如果機器上有dos/windows,可以寫到這些分區上面:
mount –r –n /dev/hda1 /mnt/had
然後就可以執行debugfs:(假設Linux在 /dev/hda5)
#debugfs /dev/hda5
就會出現debugfs提示符debugfs:
使用lsdel命令可以列出很多被刪除的檔的資訊:
debugfs:lsdel
debugfs: 2692 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
164821 0 100600 8192 1/ 1 Sun May 13 19:22:46 2001
…………………………………………………………………………………
36137 0 100644 4 1/ 1 Tue Apr 24 10:11:15 2001
196829 0 100644 149500 38/ 38 Mon May 27 13:52:04 2001
debugfs:
  列出的檔有很多(這裏找到2692個),第一欄位是檔節點號,第二欄位是檔所有者,第三欄位是讀寫許可權,接下來是檔大小,佔用塊數,刪除時間。然後就可以根據檔大小和刪除日期判斷那些是我們需要的。比如我們要恢復節點是
196829的文件:
可以先看看檔資料狀態:
debugfs:stat <196829>
Inode: 196829 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 0 Group: 0 Size: 149500
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 38
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 2001
atime: 0x31a21dd1 -- Tue May 21 20:47:29 2001
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 2001
dtime: 0x31a9a574 -- Mon May 27 13:52:04 2001
BLOCKS:
594810 594811 594814 594815 594816 594817
………………………………….
TOTAL: 38
然後就可以用dump指令恢復檔:
debugfs:dump <196829> /mnt/hda/01.sav
這樣就把檔恢復出來了。退出debugfs:
debugfs:quit
另一種方法是手工編輯inode:
debugfs:mi <196829>
Mode [0100644]
User ID [0]
Group ID [0]
Size [149500]
Creation time [0x31a9a574]
Modification time [0x31a9a574]
Access time [0x31a21dd1]
Deletion time [0x31a9a574] 0
Link count [0] 1
Block count [38]
File flags [0x0]
Reserved1 [0]
File acl [0]
Directory acl [0]
Fragment address [0]
Fragment number [0]
Fragment size [0]
Direct Block #0 [594810]
…………………………….
Triple Indirect Block [0]
使用mi指令後每次顯示一行資訊以供編輯,其他行可以直接按回車表示確認,把deletion time改成0(未刪除),Link count改成1。改好後退出debugfs:
debugfs:quit
然後用fsck檢查/dev/hda5
fsck /dev/hda5
程式會說找到丟失的資料塊,放在lost+found裏面。這個目錄裏的檔就是我們要的東東。
Now all O.K. Good Luck.


EXT3 Recovery - Score one for the fleshlings


以下轉載自上述連結:
修復ext3文件系统的超级塊
I just got my blog back after wrestling with a hosed ext3 partition, and winning. Long story short, I put some bad ram into Adrock which quickly caused a kernel panic. Upon removing the bad RAM and rebooting /var was toast, the journal was toast and it looked like the superblocks were a bit charred as well. I had to dig for a while to get this problem solved... so here's the info on the failure and the fix.
/var was unmountable.
I removed /var from fstab and booted the machine on a /var dir off the root so I could work on it remotely.
Here's what happened next. I fsck a variety of ways, fsck.ext3 etc.. each reported the same:
fsck /dev/ida/c0d0p7
fsck 1.27 (8-Mar-2002)
e2fsck 1.27 (8-Mar-2002)
Group descriptors look bad... trying backup blocks...
fsck.ext2: Invalid argument while checking ext3 journal for /var
Tried downgrading to ext2 to bypass the hosed journal issues:
tune2fs -O ^has_journal /dev/ida/c0d0p7
tune2fs 1.27 (8-Mar-2002)
tune2fs: Invalid argument while reading journal inode
No good. Tried mounting as ext2 read only:
mount -t ext2 /dev/ida/c0d0p7 /mnt -o ro
mount: wrong fs type, bad option, bad superblock on /dev/ida/c0d0p7,
or too many mounted file systems
Nada. Tried some more stuff... tune2fs, and debugfs to try to fix / disable the journal, then decided I'd better back up the partition... should have done that first! ;P
e2fsck -c /dev/ida/c0d0p7
e2fsck 1.27 (8-Mar-2002)
Group descriptors look bad... trying backup blocks...
e2fsck: Invalid argument while checking ext3 journal for /var
[root@adrock init.d]# tune2fs -j /dev/ida/c0d0p7
tune2fs 1.27 (8-Mar-2002)
The filesystem already has a journal.
[root@adrock init.d]# debugfs -w /dev/ida/c0d0p7
debugfs 1.27 (8-Mar-2002)
/dev/ida/c0d0p7: Can't read an inode bitmap while reading inode bitmap
debugfs: quit
[root@adrock init.d]# dd if=/dev/ida/c0d0p7 of=/big/var.bak.dd
530368+0 records in
Still hosed, but now I have a backup of the burnination. And now for the FIX!!!
mke2fs -S /dev/ida/c0d0p7
mke2fs 1.27 (8-Mar-2002)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
66528 inodes, 265184 blocks
13259 blocks (5.00%) reserved for the super user
First data block=1
33 block groups
8192 blocks per group, 8192 fragments per group
2016 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185
Writing superblocks and filesystem accounting information: done
That did it! mke2fs re-wrote all of the superblocks and group descriptors and I was able to mount in RO mode and copy off the data. After that I was able to fsck and remount the original parition with no problems!
I found some great info on the RedHat ext3 mailing list archive which led me to this fix. Big thanks to the guys on that list!


以下兩頁的說明, 一頁說有支援 ext3, 一頁說沒有 🙁
DEBUGFSdebugfs(8) - Linux man page


debugfs 的程式就兩個 file, 大約共 500 行. 有興趣的就於下處去看看吧~(kernel 2.6.11)
/usr/src/linux/fs/debugfs/
Kernel v2.6.11.6-bk3 fs/debugfs/
LinuxHQ - Documentation


作者: Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.

在〈檔案刪除的回復救援〉中有 2 則留言

datarecoverydownload 發表迴響取消回覆

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料