前天在尝试删除某一格式时使用了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_undelete
、photorec
使用 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