1. 程式人生 > >Linux EXT檔案系統恢復誤刪檔案的方法

Linux EXT檔案系統恢復誤刪檔案的方法

我們在管理資料庫和系統的時候,經常需要做rm 刪除檔案的操作。由於Linux是沒有回收站的,rm刪除了檔案或者目錄以後,資料是無法從Windows所謂的回收站中找到並恢復的。這樣的話,資料被誤刪除了以後,想要恢復我們一般需要從備份中,或者找資料恢復公司來恢復資料。但是,在某些比較特殊的情況下,使用了以下方法,我們還是可以找回部分資料的。
這裡我們主要介紹兩種資料恢復的方法。第一種是針對檔案在檔案系統中已經被刪除了,但是,開啟這個檔案的程序還存在。第二種針對檔案在檔案系統中已經被刪除了,目前也沒有任何程序開啟著這個檔案,但是檔案在刪除以後沒有其他對檔案系統的變更操作。
1.           從/proc檔案系統恢復資料
在Linux系統中,檔案被刪除了,只要開啟檔案的程序沒有被關閉,那麼恭喜你,這個檔案重新恢復出來的可能性非常大。因為Linux作業系統在刪除檔案時,會判斷開啟這個檔案的所有程序是否都已經關閉,如果還有一個程序沒有關閉,那麼這個檔案的空間將不會釋放。只有所有開啟這個檔案的程序都關閉以後,這個檔案的空間才會釋放。這也是為什麼在Linux下有時候我們刪除檔案,檔案的空間無法釋放掉的原因。
這種情況下,我們可以嘗試從/proc檔案系統中將檔案恢復出來。
/proc 檔案系統是一種核心和核心模組用來向程序 (process) 傳送資訊的機制 (所以叫做 /proc)。通過這個偽檔案系統讓你可以和核心內部資料結構進行互動。你可以獲取對應程序的有用資訊,在執行中 (on the fly) 通過改變核心引數修改部分設定。它與其他檔案系統不同,/proc 是存在於記憶體之中而不是硬碟上。
接下來我們模擬一下資料誤刪除的過程,來看看在程序沒有關閉的情況下,怎麼從/proc中恢復資料。
首先,我們有一個echo_red.sh的檔案,我們在會話session 1檢視一下這個檔案的內容。
此時,在另外一個會話session 2中有一個程序在修改這個檔案:
然後這個檔案在會話session 1中被我們“誤刪除”掉了:
    Session 1  Session 2 
  [
[email protected]
/home/woqu] #ll 總用量 4 -rw-r--r-- 1 root 93 10月 16 17:49 echo_red.sh [[email protected] /home/woqu] #cat echo_red.sh echo_red() {     # echo a message with red color     echo -e "\e[1;[email protected]\e[m"     return 0 }     [
[email protected]
/home/woqu] #cat >echo_red.sh echo_red() {     # echo a message with red color     echo -e "\e[1;[email protected]\e[m"     return 0 } [[email protected] /home/woqu] #rm -f echo_red.sh [[email protected] /home/woqu] #ll 總用量 0   此時,我們發現檔案被“誤刪除”了,需要恢復資料,那麼我們需要怎麼做列? l   磁碟備份 發現誤刪除以後,我們需要立刻停止對該分割槽的寫操作。 在恢復之前,如果可能的話,建議通過dd命令將磁碟整個備份起來,以避免操作的時候損壞了磁碟上相關資料。 l   確定程序號和檔案控制代碼號 首先,我們需要確定開啟這個檔案的程序號,以及程序開啟這個檔案的檔案號。最直接的辦法就是lsof |grep -i delete: [
[email protected]
/home/woqu] #lsof |grep -i delete cat       11791  root    1w      REG              253,0       94    1048589 /home/woqu/echo_red.sh (deleted) 這裡一共有9列,各列列名如下: COMMAND     PID  USER   FD      TYPE             DEVICE SIZE/OFF       NODE NAME 也就是說,開啟這個檔案的程序是11791,而/home/woqu/echo_red.sh對應該程序的檔案控制代碼是1w。也就是說檔案控制代碼號是1。 l   恢復誤刪除檔案 然後,我們就可以直接將這個檔案的內容拷貝出來:  [[email protected] /root] #cp /proc/11791/fd/1 echo_red.sh [[email protected] /root] #cat echo_red.sh echo_red() {     # echo a message with red color     echo -e "\e[1;[email protected]\e[m"     return 0 } 如上所示,資料檔案恢復出來了,內容也是一模一樣的。 2.           Extundelete工具恢復 對於使用ext3,ext4檔案系統的Linux系統有一個比較好的工具可以用於資料恢復,那就是extundelete。當然其他的檔案系統當然也有類似的恢復工具。 由於大部分Linux發行版都是以ext3,ext4作為預設檔案系統的,我們這裡以extundelete為例演示資料刪除以後恢復的相關步驟。 老規矩,首先我們需要製造一個“誤刪除”的現場。 現在我們的/home/mysql下有多個目錄,其中一個目錄為script: [[email protected] /home/mysql] #ll total 28 drwxr-xr-x 2 mysql 4096 Jul 21 14:42 bin drwxr-xr-x 2 mysql 4096 Oct 12 17:52 conf drwxr-xr-x 3 mysql 4096 Sep 26 14:57 data drwxr-xr-x 4 mysql 4096 Oct 16 15:24 program drwxr-xr-x 2 root  4096 Oct 16 18:16 script drwxr-xr-x 4 mysql 4096 Oct 16 15:25 source drwxr-xr-x 7 mysql 4096 May 31 11:27 thirdparty 這個script目錄下有一些檔案,如下: [[email protected] /home/mysql] #tree script/ script/ ├── get_mysql_fdflag.sh ├── mysqlreport.sh └── test_o_direct.c 由於某種原因,/home/mysql/script被誤刪除了。 [[email protected] /home/mysql] #rm -fr script/ l   磁碟備份 發現誤刪除以後,我們需要立刻停止對該分割槽的寫操作,避免inode被重用。 接下來就需要用extundelete工具對它進行恢復。在恢復之前如果可能的話,建議通過dd命令將磁碟整個備份起來,以避免操作的時候損壞了磁碟上相關資料。萬一extundelete或者類似的工具無法恢復資料,這些資料交給專業的硬碟恢復公司也更容易找回資料一些。 l   umount分割槽 做完了備份,我們首先做的第一步,需要將誤刪除資料的磁碟分割槽首先umount掉,這也是避免該分割槽的資料被損壞的一個步驟。在我們的模擬環境,我們需要: [[email protected] /root] #umount /home/ l   安裝extundelete 如果你機器上並沒有安裝extundelete的話,首先,你需要把這個工具安裝好。目前最新的extundelete版本是0.2.4,安裝方法如下: yum -y install e2fsprogs* wget  網頁連結 tar xjf extundelete-0.2.4.tar.bz2 cd extundelete-0.2.4/ ./configure make make install l   查詢誤刪除檔案 通過extundelete可以檢視哪些檔案被刪除了。在我們的模擬場景下,可以這樣使用extundelete --inode 2 /dev/VolGroup/home檢視/home分割槽下各個檔案和目錄的詳細資訊。這裡/dev/VolGroup/home指的是/home對應的分割槽。對於ext系列的檔案系統,編號為2的inode中包含了該分割槽下的各個檔案和目錄資訊。輸出資訊如下: [[email protected] /root] #extundelete --inode 2 /dev/VolGroup/home NOTICE: Extended attributes are not restored. Loading filesystem metadata ... 400 groups loaded. Group: 0 Contents of inode 2: 0000 | ed 41 00 00 00 10 00 00 87 99 5e 52 87 99 5e 52 | .A........^R..^R 0010 | 87 99 5e 52 00 00 00 00 00 00 05 00 08 00 00 00 | ..^R............ 0020 | 00 00 00 00 05 00 00 00 21 24 00 00 00 00 00 00 | ........!$...... 0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0080 | 1c 00 00 00 74 63 29 04 74 63 29 04 b8 23 27 8a | ....tc).tc)..#'. 0090 | e0 3e 2d 52 00 00 00 00 00 00 00 00 00 00 02 ea | .>-R............ 00a0 | 07 06 3c 00 00 00 00 00 21 00 00 00 00 00 00 00 | ..R............ 00a0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00b0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00c0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00d0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00e0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00f0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ Inode is Allocated File mode: 16832 Low 16 bits of Owner Uid: 601 Size in bytes: 4096 Access time: 1381931633 Creation time: 1381931432 Modification time: 1381931432 Deletion Time: 0 Low 16 bits of Group Id: 601 Links count: 12 Blocks count: 8 File flags: 524288 File version (for NFS): 3619593980 File ACL: 0 Directory ACL: 0 Fragment address: 0 Direct blocks: 127754, 4, 0, 0, 1, 1056800, 0, 0, 0, 0, 0, 0 Indirect block: 0 Double indirect block: 0 Triple indirect block: 0 File name                                       | Inode number | Deleted status .                                                 262145 ..                                                2 .mozilla                                          262146 .bash_profile                                     262152 .gnome2                                           262150 .emacs                                            262195 .bash_logout                                      262194 .bashrc                                           262149 bin                                               262154 conf                                              262155 data                                              262156 script                                            404044     Deleted thirdparty                                        262158 program                                           264107 .viminfo                                          262765 .bash_history                                     262193 .bzr.log                                          262153 .mysql_history                                    273588 source                                            402793 .ssh                                              414601 這裡我們誤刪除的script目錄在這裡被標記為Deleted狀態了。 l   恢復誤刪除資料 extundelete可以通過--restore-inode將指定inode對應的檔案恢復出來,也可以使用--restore-all將所有狀態為已經Deleted的檔案和目錄恢復回來。restore-inode主要用於恢復單個檔案;restore-all用於恢復所有的檔案目錄。另外,還有--restore-file,--restore-files,--restore-directory來恢復指定目錄或者檔案。 另外,如果你知道刪除的時間,那麼可以指定--after或者--before來指定誤刪除的時間。 恢復資料的時候,extundelete將在當前目錄下新建RECOVERED_FILES資料夾,並把恢復出來的資料檔案或者目錄存放在該目錄中。 比如,我們使用--restore-inode恢復資料,恢復264111號inode檔案如下: [[email protected] /root/RECOVERED_FILES] #extundelete --restore-inode 264111 /dev/VolGroup/home NOTICE: Extended attributes are not restored. Loading filesystem metadata ... 400 groups loaded. Loading journal descriptors ... 31810 descriptors loaded. [[email protected] /root/RECOVERED_FILES] #ll file. 264111 -rw-r--r-- 1 root 43816 10月 16 15:42 file.264111 如上,它恢復出來的檔案會被重新命名為file.$Inode_no(這裡是file.264111)放在RECOVERED_FILES目錄中。需要完全恢復資料的話,只需要將檔案拷貝回原目錄,並重命名。 使用restore-all恢復的話,目錄名和檔名都會恢復回來,你可以在當前目錄的RECOVERED_FILES目錄下找到對應的檔案和目錄如下: [[email protected] /root/RECOVERED_FILES] #ll mysql/ total 16 drwxr-xr-x 4 root 4096 Oct 16 15:42 script 你只需要將script拷貝到原目錄就好了。 3.           終極解決方案 當然,以上的兩個方法都是萬不得已才使用的。最好的DBA和SA永遠不是四處奔忙的救火隊員。最好的辦法是先做好預防工作,在發生之前儘量保證不出問題,而rm誤刪除檔案的預防就是對重要資料進行備份以及rm -i。 做了別名以後,刪除資料的時候,rm命令就會提示你,檔案是否確定要刪除: [[email protected] /root/RECOVERED_FILES/mysql/script] #rm sock rm:是否刪除普通檔案 "sock"? 其他避免誤刪除等故障的方法可以參考《遠離故障的十大原則》。當然,最重要的還是日常對這種不可逆操作的謹慎和小心,並及時做好備份。