使用linux时对于执行删除操作要慎之又慎,特别是重要的数据最好提前备份。当然,如果真的删除了一个文件时,我们也要冷静思考,想想如何通过其他手段弥补或减小损失。
在解决问题前,我们先了解下涉及到的基本概念:
我们看到的文件实际上是一个指向inode的链接, inode链接包含了文件的所有属性, 比如权限和所有者, 数据块地址(文件存储在磁盘的这些数据块中)。当你删除(rm)一个文件, 实际删除了指向inode的链接, 并没有删除inode的内容,进程可能还在使用。 只有当inode的所有链接完全移去,然后对应的后端数据块才会写入新的数据。
proc是linux的一个伪文件系统,用户和应用程序可以通过 proc 得到系统的信息,并可以改变内核的某些参数。
系统上的进程在/proc都有一个目录和自己的名字, 里面包含了一个fd(文件描述符)子目录(进程需要打开文件的所有链接). 如果从文件系统中删除一个文件, 此处还有一个inode的引用:
/proc/进程号/fd/文件描述符
lsof(List Open Files) 命令可以查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)等等。
模拟误删场景
准备环境
创建一个测试文件testfile,持续监听此文件。
1 | while true;do echo `date +%F-%T` >> testfile;sleep 1;done & |
开启另一个终端,将testfile删除。
1 | rm testfile |
恢复数据
使用lsof命令查看testfile文件句柄是否释放。
1 | lsof|grep testfile |
第一列是进程的名称(命令名), 第二列是进程号(PID), 第四列是文件描述符,r说明是读操作。
现在我们可以知道12376进程仍有打开文件, 文件描述符是3。
从/proc里面拷贝出删除前的数据。
1 | cp /proc/12376/fd/3 testfile.old |
接着查看下文件内容,恢复的数据可以完美对应。
1 | tail testfile.old |
最后要说的一点还是执行删除前三思后行,为了防止误操作带来的损失可以参考之前的文章,提高安全性,愿各位维护的程序永不下线,机器永不宕机。