记一次删库到数据恢复

熟悉的朋友可能知道,进入架构组后,今年一直在为团队作各类开发辅助工具,其中包括一个服务器。node

最近这个服务器也上线有三月多了,也不断收集了不少数据,包括用户的各类行为操做、API 调用数据等等。linux

在最近的一次升级中,我调整了源码的目录结构,脑子一抽删除了数据库。sql

因而就开始为期一天的数据恢复过程,最后的结果是很悲剧,好在影响不大,能够放到后面讲。shell

文件找回

须要说明的是,由于是小微服务,采用的是最简单的 SQLite 数据库。SQLite 区分其余的数据库的明显地方是,它只提供最基本的数据服务,但并不启用端口监听,能够简单的认为这就是个文件,若是删除了,就和普通文件从系统中消失是同样的。因此一般若是使用 SQLite 保存数据须要自行按期备份。数据库

因此此次的博文虽然叫『删库』,但实际上能够简单的理解成文件找回后端

rm -rf

我在误删时,是使用 rm -rf 命令,这固然是个耳熟能详的恶名远扬的命令(以致于我当时请教后端大佬的时候,后端大佬的反应是『哦,你也终于删一次库啦』)bash

rm 是 linux 系统的用于『删除文件或目录』的命令服务器

-f 标识表示 force,即:架构

在除去有写保护的文件前不提示。微服务

-r 标识表示:

当 File 参数为目录时容许循环的删除目录及其内容

FYI: 更多参考

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.
复制代码

后记

这一次的『删库』事件,给我了一个很好的教训。服务器的数据必定要及时备份或作好容灾,防止丢失。同时,此次也借此机会进行学习了文件恢复。

固然,但愿你们都不会出现我这样的悲剧 😂。


有什么问题均可以在博文后面留言,或者微博上私信我,或者邮件我 coderfish@163.com

博主是 iOS 妹子一枚。

但愿你们一块儿进步。

个人微博:周小鱼

相关文章
相关标签/搜索