恢复误删除的 Linux 文件

恢复误删除的 Linux 文件

在使用 Linux 时,有时可能会误删除某些文件。一般而言,在命令行环境下使用 rm 删除的文件是无法恢复的,但是在一些情况下还是可以恢复的。

原理

当一个文件正在被某个进程使用时,Linux 下的进程也是文件的形式存在,该文件也会被链接到该进程的虚拟文件系统下,我们只需要获取到正在运行的进程的文件描述符,就可以恢复被删除的文件了。

下面来试验一下

实验

准备工作

首先生成一个文件 test.txt,我们将要删除并恢复这个文件

1
2
3
4
cat > test.txt << EOF
Hello This is a file
to be removed and restored
EOF

接下来,我们写一个程序,这个程序将会占用 test.txt, 读取文件并输出其中的单词,输出时会等待按键,以此延迟程序退出。使用 gcc -o main main.c 编译程序运行正常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat > main.c << EOF
#include "stdio.h"
int main() {
FILE*fp = fopen("./test.txt", "r");
char key;
char* word;
while(fp != NULL) {
key = getchar();
if (key == 'q') {
break;
}
else {
fscanf(fp, "%s", word);
printf("%s", word);
}
}
fclose(fp);
}
EOF

image-20240921120602316

删除文件

打开另一个终端,运行main,但是不要让程序退出;rm -fr test.txt 删除文件。

查找占用该文件的进程

1
lsof | grep -i deleted | grep test.txt

lsof命令来自英文词组 list opened files 的缩写,其功能是查看文件的进程信息。由于 Linux 系统中的一切都是文件,因此使用lsof命令查看进程打开的文件,或是查看文件的进程信息,都能帮助用户很好地了解相关服务的运行状态。

获取到的进程信息会列出文件状态和文件名, 因此使用 grep 找到被删除的(deleted)的 test.txt

image-20240921121544694

这样就获取到了进程号

恢复文件

进入进程的目录

1
cd /proc/49864/fd

image-20240921121758449

使用 ls -l 查看文件描述符,由此可见 文件描述符3就是被删除的文件了。使用 cat 即可恢复

image-20240921122103788

总结

我们可以把这个操作打包成一个 Shell 函数,方便我们随时调用

1
2
3
4
5
6
cat >> ~/.bashrc << EOF
restore_rm() {
N="$1" ; P=/proc/$(lsof +L1 | grep "$N" | awk '{print $2}')/fd ;
ls -l $P | sed -rn "/$N/s/.*([0-9]+) ->.*/\1/p" | xargs -I_ cat $P/_ > "$N"
}
EOF

image-20240921122721300