在工作中,我們知道一些操作命令危險性很高,如: rm -rf,它會造成數(shù)據(jù)的誤刪除。如果萬一出現(xiàn)這樣情況導致數(shù)據(jù)誤刪除時,我們應(yīng)該如何對數(shù)據(jù)進行恢復呢?
刪除數(shù)據(jù)的兩種場景
通常有兩種數(shù)據(jù)刪除的場景是你需要清晰了解的。第 1 個是在執(zhí)行 rm -rf 刪除文件時,該文件正在被進程使用。第 2 個是這個文件并沒有被其他進程所使用,而被誤刪除。本課時我將圍繞這兩種場景進行講解并演示。
為什么數(shù)據(jù)可以恢復
既然我執(zhí)行了 rm -rf 命令,不就是刪除文件了嗎,為什么又可以恢復數(shù)據(jù)呢?首先我來為你介紹一下其原由,對于第 1 種進程正在使用文件的場景,數(shù)據(jù)可以恢復是由因為 Linux 里,每個文件都有 2 個 link 計數(shù)器:i_count 和 i_nlink。
i_count 的作用是當一個文件被一個進程引用時,它的數(shù)值會加 1,也就是說它記錄的是文件被進程引用的次數(shù)。i_nlink 的作用則是記錄文件產(chǎn)生硬鏈接的個數(shù)。Linux 系統(tǒng)只有在兩個數(shù)值都清零的時候,文件才被系統(tǒng)認為是刪除的。如果我們執(zhí)行了 rm -rf,卻并沒有把 i_count 刪除,假設(shè)此時刪除文件有進程在使用,那么它(i_count)數(shù)值不為 0。這個時候就是文件看似被刪除,但在操作系統(tǒng)還是能便捷的恢復回來。
這就是第 1 種場景刪除數(shù)據(jù)能夠被找回的原因(由于 i_count 不為 0)。
第 2 種場景是將沒有被進程使用的文件誤刪除,此時 i_count 和 i_nlink 都為 0。這個時候文件的 inode 連接信息已經(jīng)被刪除了,我們就需要通存放文件的 block 單元,做數(shù)據(jù)塊的數(shù)據(jù)找回。在系統(tǒng)上我們能看到的文件內(nèi)容包括:文件名、文件大小、內(nèi)容,但實際上它的存儲依賴兩個非常重要的單元,一個是 inode,它用于存放文件的相關(guān)元數(shù)據(jù),它的元數(shù)據(jù)里會有一個類似于索引的值,能夠索引到后面具體存放數(shù)據(jù)的 block 單元, block 是一個數(shù)據(jù)塊,用來實際存放數(shù)據(jù)。我們在刪除文件時,其實是把 inode 的鏈接刪除了,但是 block 數(shù)據(jù)塊,并沒有刪除。
所以這個時候我們依然可以通過分析后端的 block 塊,對文件進行恢復。因為 block 塊保存著真實的數(shù)據(jù),理論上可以作完整的找回數(shù)據(jù),不過有一個風險:如果有進程在不斷往磁盤寫數(shù)據(jù)時,需要申請新的 block 塊,如果操作系統(tǒng)分配已刪除文件的 block 塊時,那么新的寫入數(shù)據(jù)就會覆蓋 block 原來的數(shù)據(jù),這時就會造成數(shù)據(jù)真正丟失的風險。
所以,如果出現(xiàn)這樣場景造成數(shù)據(jù)誤刪除,需要第一時間 umount 目錄所在的磁盤設(shè)備。如果沒有其他進程在不斷地往同一個磁盤塊(block)里寫數(shù)據(jù),那么你的數(shù)據(jù)理論上還是在 block 塊里面,依然可以通過相關(guān)分析把數(shù)據(jù)找回。
這就是我們?yōu)槭裁纯梢栽谶@兩個場景中把數(shù)據(jù)找回的原因,那么接下來我將講解如何來恢復數(shù)據(jù)。我會通過兩個案例來進行演示。
案例演示
我們先演示第 1 種場景,第 1 種場景是文件在被進程使用過程中被刪除,這種場景該如何去恢復文件呢?
首先我登錄到測試環(huán)境的機器上,這里開啟了兩個窗口,第 1 個窗口我登錄到了這臺服務(wù)器上,cd /test 目錄下,echo 一個測試文件(我把它命名為 DeleteFile),然后把這個內(nèi)容("Delete file")重定向到本地的 deletefile.txt。這個時候我的測試文件就已經(jīng)生成了。接下來我要做的是開啟一個進程,讓它實時地使用這個文件。
這里我使用 tail 命令,持續(xù)地查看并且保持監(jiān)聽并使用這個文件。
接下來在另一個窗口,我同樣到/test 目錄下,而此時我要執(zhí)行的是 rm -rf ./deletefile.txt,這樣就“徹底”把這個文件刪除。接下來我們通過 ls,可以看到本地已經(jīng)沒有這個文件了。
現(xiàn)在我們已經(jīng)模擬出文件在進程使用過程中被刪除的場景,那么接下來我們來演示恢復該文件。
首先需要找到是哪個進程在使用這個文件,我們可以通過 lsof 命令,grep 剛剛刪除的文件名稱(deltefile.txt),會列出當前使用文件的進程。我們會看到tail 命令正在使用,它(進程)的 pid 是 4701。
接下來我們要根據(jù)這條線索去恢復數(shù)據(jù)。我們知道該進程會有使用的文件句柄,那么我們對該進程的文件句柄目錄進行查找,cd 到 /proc/{pid}/fd 目錄下(這里 pid 為4701),我們到這個目錄下,輸入 ls -l 命令,這個時候我們會看到,使用這個文件(/test/deletefile.txt)并且它的文件句柄為 3。
接下來我們要想辦法把這個文件進行恢復,輸入cp 3 /opt/recovertest/deletefile.txt_bak,這時我就把這 3 個文件做了一個拷貝,實現(xiàn)將數(shù)據(jù)恢復到 /opt/recovertest/deletefile.txt_bak 文件。
這個時候cd /opt/recovertest/,cat deletefile.txt_bak 看一下里面的內(nèi)容,可以發(fā)現(xiàn)這個文件的內(nèi)容與剛剛生成的的測試文件內(nèi)容一致,所以剛剛刪除的文件恢復完畢。
接下來我來演示誤刪數(shù)據(jù)場景2(在沒有進程使用文件的情況下,如何恢復誤刪的文件)。演示這種場景,保險起見我在本地多掛載了一塊 SDB 的獨立硬盤設(shè)備。
這種情況要如何恢復數(shù)據(jù)呢?我們需要安裝 extundelete 這個工具。登錄到我的測試機上,在這個演示場景里,掛載一塊獨立硬盤設(shè)備 /dev/sdb 并作數(shù)據(jù)格式化。完成格式化后。把單獨的 sdb 設(shè)備,掛載到 test 目錄下(mount /dev/sdb /test),接下來在 test 目錄下生成一個內(nèi)容為“deletetest ”的測試文件file(echo 'deletetest'>file),這個時候本地目錄會生成一個測試的文件:file,再新建一個叫 testdir 的目錄(mkdir /test/testdir),那么這時本地既有文件又有目錄,也就是我接下來要演示刪除的這些文件。
我們可以通過 rm -rf ./*,直接把當前目錄下的文件整體刪除。然后我需要恢復這個文件,原理就是:通過分析它的 block 塊,來恢復 inode 鏈接,要分析并恢復已刪除文件的鏈接,我們要用到一些工具,這里推薦你使用一個叫 extundelete 的命令,它是在 Linux 下基于 ext3\ext4 的文件分析工具,可以對文件系統(tǒng)已刪除的文件進行分析,并進行數(shù)據(jù)恢復。
在執(zhí)行命令extundelete之前需要先做的是 umount,把我們剛剛誤刪的目錄 umount 掉(umount ?/test -l),避免有新的進程再往磁盤塊里寫數(shù)據(jù),同時也便于執(zhí)行工具進行接下來的分析。
附:extundelete 命令安裝方式:
yum -y install bzip2 e2fsprogs e2fsprogs-devel gcc-c++
wget https://nchc.dl.sourceforge.net/project/extundelete/extundelete/0.2.4/extundelete-0.2.4.tar.bz2
tar jxvf extundelete-0.2.4.tar.bz2?
cd extundelete-0.2.4
./configure?
make && make install
安裝好這個工具(extundelete)后,執(zhí)行:extundelete /dev/sdb --inode 2
我們可以在命令后面加入設(shè)備名稱,然后加入上面的 inode 進行分析。完成之后我們會看到顯示屏幕上已經(jīng)出現(xiàn)了剛剛刪除的文件、名稱及目錄,還會看到 inode 號以及當前的狀態(tài)。
我們也可以選擇恢復單獨文件類型文件,執(zhí)行:extundelete /dev/sdb --restore-file file
加入的選項是 --restore-file,后面加你想恢復的文件名稱。
在執(zhí)行以上恢復操作之前,我先要確保數(shù)據(jù)恢復的目錄 /opt/recovertest 下,cd ?/opt/recovertest 目錄下,執(zhí)行想恢復的文件 extundelete /dev/sdb --restore-file file。
執(zhí)行完命令后,會有一個成功的提示。此時在當前目錄的 RECOVERED_FILES 目錄,有對應(yīng)恢復好的文件,一個是 file,一個是 file.v1(這個為剛恢復的文件),為什么是 file.v1 呢?因為我在做操作的時候有操作過兩遍,所以它恢復了兩個文件。第 1 個 file 是我之前寫入的內(nèi)容,第 2 個 file 則是由于我執(zhí)行了第 2 次恢復,恢復的文件雖然也是 file,所以會自動命名成一個新的版本,叫作 file.v1(這個文件就是我們想要恢復的文件名稱)。
剛剛講到的選項是恢復單個文件,假設(shè)我們要恢復所有文件的話,就把選項改為 --restore-all,這樣就把分析出來的已刪除文件進行了恢復。如果件,只想恢復某一個目錄,就可以把 "all" 改成 directory,然后用 restore-directory 這種方式恢復單個已刪除的文件目錄。
以上就是通過 extundelete 作場景 2 恢復演示。
平時工作中,你還是需要謹慎進行操作系統(tǒng)指令,以避免產(chǎn)生文件系統(tǒng)誤刪的情況,畢竟恢復起來對我們的業(yè)務(wù)影響,還有數(shù)據(jù)風險都是存在的。