恢复XFS文件系统中误删文件

前天在尝试删除某一格式时使用了find . -name *.nfo -delete命令,执行时并没有事先做确认,导致执行后将该目录下所有文件全部都删除了。

这一命令事后我尝试在Mac复现时发现在某些目录下,总会将所有文件都找出,而且不论是bash还是zsh都有问题,同一目录在Linux上就是正常的结果。本以为时macOS的bug时,尝试cd切换别的目录再还回来后,又正常了……

先不管问题原因,本文主要介绍在XFS下误删文件后该怎么恢复。
以下所有命令基本都需要使用root用户执行。

止损

停止写入

在发现误删文件后,首先要做的就是停止所有正在或可能向该硬盘读写的程序,避免新数据覆盖,导致将来无法恢复数据。 Linux中使用lsof查看当前读写硬盘的程序

lsof /data
COMMAND       PID  USER   FD   TYPE DEVICE  SIZE/OFF    NODE NAME
xxx 123 user  mem    REG  253,2           5116547 /data/xxx

解挂载磁盘

结束所有当前读写程序后,解挂载磁盘,避免定时任务等可能会影响数据恢复的程序。

# 解挂载
umount /data

# 查看是否成功解挂
df -hT | grep /data

原理

众所周知,在系统中删除文件并不会立即执行擦除文件,而会将链接数设置为0。恢复工具会遍历B+树,试图理解存储在inode中的外延信息并收集文件的数据块。

inode 内容

inode包含以下内容(参考阮一峰博文)

  • 文件的字节数
  • 文件拥有者的 User ID
  • 文件的 Group ID
  • 文件的读、写、执行权限
  • 文件的时间戳,共有三个:ctime 指 inode 上一次变动的时间,mtime 指文件内容上一次变动的时间,atime 指文件上一次打开的时间。
  • 链接数,即有多少文件名指向这个 inode
  • 文件数据 block 的位置

这是理论上能恢复的所有内容,而由于inode不包含文件名,所以恢复出来的文件的文件名称会丢失。扩展名是根据文件内容进行猜测的,所以扩展名可能也与原始文件的有出入。

恢复数据

Ext3、4下有很多成熟的恢复工具,XFS下免费、开源的数据目前找到两款——xfs_undeletephotorec

使用 xfs_undelete 恢复

xfs_undelete 是一款专门针对XFS文件系统的误删文件恢复工具。

安装运行库

xfs_undelete 是使用 Tcl 语言编写的,执行时需要先安装 Tcl库。

# 红帽系
yum install -y tcllib

# Debian、Ubuntu系
apt install -y tcllib

下载

xfs_undelete本身是脚本,不需要编译。直接从Github中可下载程序,或直接点击下载当前最新版v11

wget https://github.com/ianka/xfs_undelete/archive/refs/tags/v11.0.zip
unzip v11.0.zip
cd xfs_undelete-11.0

执行

直接执行即可扫描并查看可恢复文件

./xfs_undelete 设备
xfs_undelete [ -t timespec ] [ -T timespec ] [ -r filetypes ] [ -i filetypes ] [ -z filetypes ] [ -o output_directory ] [ -s start_inode ] [ -m magicfiles ] [ --no-remount-readonly ] device
xfs_undelete -l [ -m magicfiles ]

参数

时间

-t-T 都是限定时间区间,区别为 -t 控制删除时间,-T 控制修改时间。

# 恢复2小时内删除的文件
xfs_undelete -t -2hour /dev/sdb
# 恢复2022-01-01后删除的文件
xfs_undelete -t 2022-01-01 /dev/sdb

# 恢复2小时内修改过的文件
xfs_undelete -T 2hour /dev/sdb
# 恢复2022-01-01后修改过的文件
xfs_undelete -T 2022-01-01 /dev/sdb

类型

-r-i-z 后面都是跟文件类型。

-r 表示仅恢复特定格式文件,默认为全部文件。

-i 忽略特定格式文件,默认过滤二进制文件。

-z 表示删除文件尾部连续的0

*/*表示全部文件,具体类型写法参考mimetypes,多个文件类型以逗号分隔。

# 仅恢复图片,且扩展名以 gimp- 开头的文件
xfs_undelete -r 'image/*,gimp-*' /dev/sdb
# 恢复所有文件(包含默认过滤的二进制文件)
xfs_undelete -i "" /dev/sdb
# 删除恢复文本文件尾部的0
xfs_undelete -z text/* /dev/sdb

输出

-o 将文件恢复到什么目录。显然你无法将恢复后的文件保存到源硬盘,所以需要另备一块硬盘储存恢复文件。

# 将 sdb 中已删除的文件恢复到 /mnt
xfs_undelete -o /mnt/ /dev/sdb

更多参数

还有些不太用得上的参数,参考官网文档,或者man查看。

使用 TestDisk 恢复

TestDisk官网 可以下载各个平台的可执行文件。

TestDisk 使用就是非常傻瓜式了,为字符交互界面,以amd64的Linux为例

wget https://www.cgsecurity.org/testdisk-7.2-WIP.linux26-x86_64.tar.bz2
tar xvf testdisk-7.2-WIP.linux26-x86_64.tar.bz2
cd testdisk-7.2-WIP
./photorec_static

接下来会扫描系统中的所有硬盘,让你选择需要恢复哪块硬盘,再然后让你选择文件系统,分ext3、4和其他两种,选其他后会让你选恢复目录,确认后会将所有能恢复的文件都恢复到该目录。没有什么高级选

结果

使用xfs_undelete恢复,结果是并没有将设置的时间段内删除的文件都恢复出来,只恢复出一部分。

使用photorec恢复,由于无法控制恢复时间段,所以需要遍历硬盘,导致花费时间要远远远远超过xfs_undelete,且由于无法限定恢复文件类型,导致大量并不再需要的文件被恢复了,而且恢复出的文件中又不少都无法正确打开。

两款恢复工具效果都差强人意,只能在没有备份的情况下尽可能减少损失。且由于会丢失文件名及文件结构,所以比较适合视频等名称、结构不敏感的。如果误删除的是项目、应用程序或者数据库等内容,恢复出来的内容完全不可用。

教训

命令行执行删除、批量替换等破坏性操作时,一定要先输出查看,确认没问题后再删。

一定要定期备份,且备份和原始文件决不能放在同一块硬盘上。


最后修改于 2022-05-12