在进行采集日志时,日志文件明明被滚动压缩并转移走了,但是发现磁盘空间还是在不断增长,统一目录下的总文件大小,发现与实际占用也不符,于是想到可能是文件句柄未释放导致的,本文就来记录一下文件及文件句柄查看相关的内容,方便查阅。
在 linux 中,一切皆文件,我们最熟悉的创建目录,创建文件,查看文件
mkdir test_dir
cd test_dir
touch test.log
ls -al
而对于文件来说,实际上是一个指向inode的链接, inode链接包含了文件的所有属性, 比如权限和所有者, 数据块地址(文件存储在磁盘的这些数据块中)。
当你删除(rm)一个文件时, 实际删除了指向inode的链接, 并没有删除inode的内容, 进程可能还在使用,只有当inode的所有链接完全删除后, 然后这些数据块才可以写入新的数据。
所谓的指向inode的链接,其实就是指 fd 文件描述符,我们来实际操作一下,理解一下上面的概念
查看文件 inode
如何查看文件的 inode 呢? ls 的 -i
参数可以查看文件的 inode 编号
ls -ali
total 8
1970254 drwxr-xr-x 2 root root 4096 Oct 18 16:03 .
2097155 drwx------ 1 root root 4096 Oct 18 16:03 ..
1970255 -rw-r--r-- 1 root root 0 Oct 18 16:03 test.log
其中第一列就是 inode 编号
我们在进行 mv 操作时,虽然文件名改变了,但是 inode 是不变的,你可以仅仅认为名称是一个软连接一样,文件本质不变
mv test test1.log
ls -ali
通过 inode 删除文件
通常情况下,我们直接使用 rm 命令就可以删除文件,但是如果遇到一些特殊字符(控制字符,乱码字符)之类的文件,键盘都打不出来,怎么办呢?这时候可以通过 find 配合 inode num 来删除文件。
find ./ -inum 1970255 -delete
文件句柄占用
终于来到了开头提到遇到的问题了,有时候我们发现了文件,但是空间并没有释放的问题,这个问题的原因就是文件句柄还在被进程占用导致的,我们来模拟一下。
touch a.log
echo aa > a.log
# 使用 tail 命令保持对 a.log 的监听
tail -f a.log
再打开一个终端窗口,删掉 a.log, 然后通过 lsof 命令查看文件句柄占用情况。
rm a.log
# 找到 tail 的进程号
ps -ef | grep tail
# 查看文件句柄的占用情况
lsof -p 7414
发现有一个 deleted 标识的 fd 占用,当前目录下已经没有 a.log 文件了,但是其实这个文件还没有释放。
查看进程打开的描述符,确实 tail 进程还占用着
# ls -al /proc/{进程ID}/fd/ 查看进程打开的 fd
ls -al /proc/7414/fd/
这时唯一的解决办法就是将 tail 进程关掉,这个文件才会被真正的删掉
END
好了,今天的分享就到这里,关注我,和我一起学习成长。
感谢大家的阅读,如果有任何异议的地方,欢迎指正,也欢迎大家公号找到我与我做朋友!