1.背景

如果使用rm -rf 误删除数据,我们怎么恢复误删除的数据呢?

2.场景分析

删除数据主要有两种场景:

  • 场景一 在执行rm -rf 删除文件时,该文件正在被进程使用。
  • 场景二 这个文件没有被进程占用,从而被误删除
i_count: 当一个文件被一个进程引用时,它的数值会加1,也就是说它记录的是文件被进程引用的次数。
i_nlink: 记录文件产生硬链接的个数。
Linux系统只有在两个数值都清零的时候,文件才被系统认为是删除的,假设此时删除文件有进程在使用,那么i_conunt数值不为0。
场景二,此时i_count和i_nlink都为0,inode连接信息已经被删除了,我们就需要通过存放文件的block单元,做数据块的数据找回。
找回数据需要依赖两个关键的参数:
inode: 用于存放文件的相关元数据,它的元数据里会有一个类似于索引的值,能够索引到后面具体存放数据的block单元
block: 是一个数据块,用来实际存放数据
所以理论上可以通过block块找回数据,因为上面保存着真实的数据。
风险:如果有进程在在不断地往磁盘写数据时,需要申请新的block块,如果操作系统分配已删除的block块时,新写入的数据就会覆盖原来的数据,此时就会造成数据真正丢失。
在这种情况下,应该第一时间umount目录所在的磁盘,或者不对磁盘进行任何写入,以保证理论数据还存在磁盘上,那么还可以通过相关分析找回数据。

3.场景一演示

场景一搭建:

首先准备测试的文件aaa.txt,内容为运维贼船公众号的域名,在终端一中执行:

# 创建测试文件夹
mkdir /tmp/test
# 创建测试文件
echo "aaa.al" > /tmp/test/aaa.txt

image-20240228104651503

创建完文件后,使用进程打开它并保持占用,这里用tail -f来模拟:

tail -f /tmp/test/aaa.txt

image-20240228104705606

此时,新开一个终端二,删除aaa.txt文件。

rm -rf /tmp/test/aaa.txt

image-20240228104718375

此时的状态为终端一仍在占用进程,终端二中把文件删除掉了。

场景一恢复:

下面执行恢复操作,使用lsof命令:

# lsof | grep 删除的文件名,如:
lsof | grep aaa.txt

可以看到查询出来的结果处于“deleted”的状态,我需要找到此进程的pid,比如我这里的结果pid为1364000。

image-20240228104803072

根据pid号查找文件句柄:

# cd /proc/记录的pid号/fd,如:
cd /proc/1364000/fd
ll

image-20240228104816363

恢复文件,执行以下命令,可以看到数据已经恢复回来了。

cp 3 /tmp/test/aaa.txt.bak
cat /tmp/test/aaa.txt.bak

image-20240228104829265

4.场景二演示

场景二搭建:

我们这里使用单独的一块硬盘来做演示,我这里的硬盘是/sdb1,格式为ext3.

image-20240228104840445

挂载的目录为/test

image-20240228104852375

我这里在挂载的目录创建aaa.txt,写入内容和aaa的文件夹。
echo "aaa.al" > /test/aaa.txt
mkdir -p  /test/aaa
cd /test
ls

image-20240228104906859

然后对硬盘内容删除:
cd /test
rm -rf *
ls

image-20240228104918049

场景二恢复:

恢复前需要对硬盘进行取消挂载:
umount /test -l
# 创建一个用于恢复数据的目录
mkdir /tmp/test
cd /tmp/test
执行extundelete命令,如果没有此命令,可以直接安装:
yum -y install epel-release
yum -y install extundelete
完成后,执行命令,可以看到最后显示出误删除的文件,状态为Deleted。
extundelete /dev/sdb1 --inode 2

image-20240228104932708

开始恢复文件,找到我们需要恢复文件的Inode number,比如我这里图示为12,则执行以下命令。

extundelete /dev/sdb1 --restore-inode 12
执行后,会在当前目录下生成RECOVERED_FILES目录,里面包含我们恢复的文件:

图片image-20240228104944407

通过查看文件内容,发现和我们需要恢复的文件一致,只是文件名不一样,手动修改即可。

image-20240228105005261

同样的方式,我们还可以恢复文件夹和所有文件,命令格式如下:

1)通过inode号(extundelete /dev/sdb1 --restore-inode InodeNum)
2)通过file文件名(extundelete /dev/sdb1 --restore-file FileName)
3)通过directory目录名(extundelete /dev/sdb1 --restore-directory DirectoryName)
4)all全部恢复(extundelete /dev/sdb1 --restore-all)

5.总结

通过上面演示的场景一,文件进程在使用中被删除;场景二未有进程占用时文件被删除两种情况做了演示恢复的操作。需要注意的是,extundelete仅支持ext系列格式分区,不支持xfs文件系统,如果需要恢复xfs文件,可以关注我后续的文章,谢谢!