記一次刪庫到數(shù)據(jù)恢復(fù)
記一次刪庫到數(shù)據(jù)恢復(fù)
熟悉的朋友可能知道,進(jìn)入架構(gòu)組后,今年一直在為團(tuán)隊(duì)做各種開發(fā)輔助工具,其中包括一個(gè)服務(wù)器。
最近這個(gè)服務(wù)器也上線有三月多了,也不斷收集了很多數(shù)據(jù),包括用戶的各種行為操作、API 調(diào)用數(shù)據(jù)等等。
在最近的一次升級(jí)中,我調(diào)整了源碼的目錄結(jié)構(gòu),腦子一抽刪除了數(shù)據(jù)庫。
于是就開始為期一天的數(shù)據(jù)恢復(fù)過程,***的結(jié)果是很悲劇,好在影響不大,可以放到后面講。
文件找回
需要說明的是,因?yàn)槭切∥⒎?wù),采用的是最簡(jiǎn)單的 SQLite 數(shù)據(jù)庫。SQLite 區(qū)分其他的數(shù)據(jù)庫的明顯地方是,它只提供最基本的數(shù)據(jù)服務(wù),但并不啟用端口監(jiān)聽,可以簡(jiǎn)單的認(rèn)為這就是個(gè)文件,如果刪除了,就和普通文件從系統(tǒng)中消失是一樣的。所以通常如果使用 SQLite 保存數(shù)據(jù)需要自行定期備份。
所以這次的博文雖然叫『刪庫』,但實(shí)際上可以簡(jiǎn)單的理解成文件找回。
rm -rf
我在誤刪時(shí),是使用 rm -rf 命令,這當(dāng)然是個(gè)耳熟能詳?shù)膼好h(yuǎn)揚(yáng)的命令(以至于我當(dāng)時(shí)請(qǐng)教后端大佬的時(shí)候,后端大佬的反應(yīng)是『哦,你也終于刪一次庫啦』)
rm 是 linux 系統(tǒng)的用于『刪除文件或目錄』的命令
-f 標(biāo)識(shí)表示 force,即:
- 在除去有寫保護(hù)的文件前不提示。
-r 標(biāo)識(shí)表示:
- 當(dāng) File 參數(shù)為目錄時(shí)允許循環(huán)的刪除目錄及其內(nèi)容
extundelete 與磁盤存儲(chǔ)
extundelete 是 linux 系統(tǒng)下一個(gè)有力的數(shù)據(jù)恢復(fù)工具。extundelete使用存儲(chǔ)在分區(qū)日志中的信息來嘗試恢復(fù)已從分區(qū)中刪除的文件。
我們稍微復(fù)習(xí)一下計(jì)算機(jī)基礎(chǔ)知識(shí):
硬盤
硬盤是一種采用磁介質(zhì)的數(shù)據(jù)存儲(chǔ)設(shè)備,數(shù)據(jù)『物理意義上的』存儲(chǔ)在若干個(gè)磁盤片上。在磁盤片的每一面上,以轉(zhuǎn)動(dòng)軸為軸心、以一定的磁密度為間隔的若干個(gè)同心圓就被劃分成磁道(track),每個(gè)磁道又被劃分為若干個(gè)扇區(qū)(sector)。
主引導(dǎo)扇區(qū)和分區(qū)表
硬盤的0磁道0柱面1扇區(qū)是主引導(dǎo)扇區(qū)位,包括硬盤主引導(dǎo)記錄MBR(Main Boot Record)和分區(qū)表DPT(Disk Partition Table)。操作系統(tǒng)通過分區(qū)表把硬盤劃分為若干個(gè)分區(qū),然后再在每個(gè)分區(qū)里面創(chuàng)建文件系統(tǒng),寫入數(shù)據(jù)文件。
分區(qū)日志
分區(qū)日志系統(tǒng)是一個(gè)文件系統(tǒng),用于修復(fù)由于計(jì)算機(jī)關(guān)閉不當(dāng)而導(dǎo)致的任何不一致。這種關(guān)閉通常是由于電源中斷或軟件問題造成的。即記錄了分區(qū)的數(shù)據(jù)讀寫操作。
通過這些日志,可以知道分區(qū)中的歷史操作。
數(shù)據(jù)存儲(chǔ)
具體的數(shù)據(jù)存儲(chǔ)原理內(nèi)容比較多,這里不做贅述。為了便于理解,我在此理解為:
- 操作系統(tǒng)中的文件在硬盤的表現(xiàn)形式是在硬盤一片數(shù)據(jù)區(qū)域記錄二進(jìn)制信息,并由操作系統(tǒng)的一個(gè)指針指向該物理地址
- 而操作系統(tǒng)級(jí)別的『刪除文件』,即刪除這個(gè)『指針』
- 原來的物理地址內(nèi)沒有『指針』指向后,相當(dāng)于被釋放,當(dāng)操作系統(tǒng)需要時(shí),可以被復(fù)寫上新的數(shù)據(jù)。
由此觀得,extundelete 通過查閱分區(qū)日志,找到被刪除的指針,告訴用戶,可以嘗試恢復(fù)哪些數(shù)據(jù)。
但由于操作系統(tǒng)隨時(shí)可以復(fù)寫空余磁盤,所以如果要恢復(fù)的物理地址已經(jīng)被改寫,數(shù)據(jù)將無法找回。
DEMO
為了脫敏,我使用我自己的服務(wù)器,具體記錄一下文件恢復(fù)的過程。
- 環(huán)境
- CentOS 7.4 64位
文件目錄: /root/Sparrow/db.sqlite3
刪除文件
- # rm -rf db.sqlite3
安裝 extundelete
- # yum install extundelete -y
掛載磁盤
首先我們?nèi)ゲ樵冞@個(gè)文件或上級(jí)文件夾所處的磁盤
- # df /root/Sparrow/
- 文件系統(tǒng) 1K-塊 已用 可用 已用% 掛載點(diǎn)
- /dev/vda1 41151808 2614640 36423736 7% /
找到后首要的是掛載磁盤,掛載后磁盤將不會(huì)被繼續(xù)寫入,保護(hù)現(xiàn)場(chǎng)
- umount /dev/vda1
/dev/vda1 就是文件所在的磁盤。
不掛載也是可以的,這樣會(huì)導(dǎo)致磁盤可能會(huì)被其他的進(jìn)程寫入數(shù)據(jù),從而抹掉原來的數(shù)據(jù),所以我***沒有找回文件就是因?yàn)闆]有及時(shí)掛載。
inode
inode 是 linux 系統(tǒng)下文件或者文件夾的標(biāo)識(shí)。通過 ls –id 就可以看到。
讀取根目錄的 inode 值:
- # ls -id /
- 2 /
現(xiàn)在我們知道磁盤根目錄的 inode 是 2。
extundelete 查詢可恢復(fù)的數(shù)據(jù)信息
先查詢磁盤根目錄下的可恢復(fù)信息
- # extundelete /dev/vda1 --inode 2
執(zhí)行時(shí),如果沒有掛載磁盤,會(huì)提示。
得到結(jié)果:

重點(diǎn)盤紅圈內(nèi),看到 root 的 inode 是 131073,繼續(xù)查詢 /dev 的信息:
- # extundelete /dev/vda1 --inode 131073

看到 /Sparrow 是 262194,繼續(xù)查詢 /dev 的信息:
- # extundelete /dev/vda1 --inode 262194
最終找到了刪除信息:

可以看到 db.sqlite3 被標(biāo)識(shí)為 Deleted。
extundelete 恢復(fù)數(shù)據(jù)
執(zhí)行 –restore-directory 恢復(fù)指定目錄
- # extundelete /dev/vda1 --restore-directory /root/Sparrow/db.sqlite3
或執(zhí)行 –restore-all 恢復(fù)所有可恢復(fù)的數(shù)據(jù)
- # extundelete /dev/vda1 --restore-all
執(zhí)行結(jié)束后,會(huì)在當(dāng)前路徑下,生成一個(gè) RECOVERED_FILES 文件夾,里面有所有被恢復(fù)的文件。
如果磁盤已經(jīng)被讀寫,無法恢復(fù),會(huì)提示類似信息:
- Loading filesystem metadata ... 320 groups loaded.
- Loading journal descriptors ... 27896 descriptors loaded.
- Searching for recoverable inodes in directory /root/Sparrow/db.sqlite3 ...
- 120 recoverable inodes found.
- Looking through the directory structure for deleted files ...
- 120 recoverable inodes still lost.
- No files were undeleted.
后記
這一次的『刪庫』事件,給我了一個(gè)很好的教訓(xùn)。服務(wù)器的數(shù)據(jù)一定要及時(shí)備份或做好容災(zāi),防止丟失。同時(shí),這次也借此機(jī)會(huì)進(jìn)行學(xué)習(xí)了文件恢復(fù)。
當(dāng)然,希望大家都不會(huì)出現(xiàn)我這樣的悲劇 😂。