Linux中删除文件的原理
Linux中的文件被分为用户数据和文件元数据。Linux中文件数据都存储在块中(常见块的大小是4KB,即连续8个扇区sector组成一个块block),而文件的元数据,例如文件的创建者、文件的创建日期、文件的大小等等,都是存贮在叫做inode区域中的。中文译名索引节点。
Linux是通过link的数量来控制文件删除的,只有当一个文件不存在任何link的时候,这个文件才会被删除。一般来说,每个文件都有2个link计数器:i_count 和 i_nlink。
i_count 和 i_nlink,从VFS inode结构体中可以找到:
struct inode {
struct hlist_node i_hash;
struct list_head i_list;
struct list_head i_sb_list;
struct list_head i_dentry;
unsigned long i_ino; //索引节点号
atomic_t i_count; //引用计数器
unsigned int i_nlink; //硬链接数目
i_count:当前文件使用者(或被调用)的数量
i_nlink:介质连接的数量(硬链接的数量)
当一个文件被某一个进程引用时,对应i_count数就会增加;当创建文件的硬链接的时候,对应i_nlink数就会增加。
对于删除命令rm而言,实际就是减少磁盘引用计数i_nlink。如果该文件正在被某个进程调用,比如系统正在写入的日志文件,执行了rm操作,虽然目录看不到了日志文件,但没有真正删除这个文件,i_count并不为0,你通过df统计就发现磁盘还没有释放。当只有i_nlink及i_count都为0的时候,这个文件才会真正被删除。
du与df统计结果不一致
du: disk usage
通过搜索文件来计算每个文件的大小然后累加得到的值。
du会把指定目录下所有文件、目录、目录下的文件都统计。是建立在文件系统能看到的的确确是有这样一些文件的基础上的。也就是说我们能在文件系统里面看到的文件才会被du统计。
df: disk free
通过文件系统来获取空间大小的信息。
df(df命令通过查看文件系统磁盘块分配图得出总块数与剩余块数)
这要从程序写文件的方式来谈起,一个进程要向一个文件里面写东西,那么会得到一个pointer,然后向指针指向的文件(磁盘区域)写入。假如由于某些原因(也可能人为)被指向的文件被删除了,但是( write call)并不知道文件是否还在,就还会继续向里面写,不管文件是否存在,磁盘块还是被写操作使用。于是因为文件没有了,所以du统计不到写入的这些磁盘块,但是因为写的进程还在,磁盘空间没有被释放,所以df却能统计到,所以df统计的结果比du大很多。
利用proc目录恢复被删除的文件
上面说到被进程占用的日志文件rm操作,并没有真正被删除,既然没有真正被删除,如何恢复它呢。
[root@ky35z ask]# rm -rf info.log
[root@ky35z ask]# ls -lrt info.log
ls: cannot access info.log: No such file or directory
在/proc[pid]/fd目录下,保存了所有进程打开的文件。也就是说,虽然从文件系统层面,我们已经无法找到已经被删除的文件,但是,我们还可以在proc目录下找到该文件的文件句柄。
1.找到占用该日志文件的进程号
[root@ky35z fd]# lsof | grep info.log
java 8337 root 53w REG 253,1 528 1444660 /ask/info.log (deleted)
2.进入该进程的/proc/pid/fd目录
[root@ky35z ask]# cd /proc/8337/fd
3.在proc目录下找到该文件的文件句柄
[root@ky35z fd]# ls -lt
l-wx------ 1 root root 64 Nov 1 11:31 48 -> /ask/info.log
4.直接对文件句柄进行拷贝
[root@ky35z fd]# cp /proc/8337/fd/48 /ask/info.log
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。