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

重點盤紅圈內,看到 root 的 inode 是 131073,繼續查詢 /dev 的信息:
- # extundelete /dev/vda1 --inode 131073

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

可以看到 db.sqlite3 被標識為 Deleted。
extundelete 恢復數據
執行 –restore-directory 恢復指定目錄
- # extundelete /dev/vda1 --restore-directory /root/Sparrow/db.sqlite3
或執行 –restore-all 恢復所有可恢復的數據
- # extundelete /dev/vda1 --restore-all
執行結束后,會在當前路徑下,生成一個 RECOVERED_FILES 文件夾,里面有所有被恢復的文件。
如果磁盤已經被讀寫,無法恢復,會提示類似信息:
- 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.
后記
這一次的『刪庫』事件,給我了一個很好的教訓。服務器的數據一定要及時備份或做好容災,防止丟失。同時,這次也借此機會進行學習了文件恢復。
當然,希望大家都不會出現我這樣的悲劇 😂。