Df 与 Du 结果不匹配问题
du 与 df 与 文件描述符不得不说的故事
案发现场
开发同学接到了 cacti 的预警. 一台生产机器硬盘吃紧, 使用量达到了 90% 以上
这里不方便给截图, 请看官们自行脑补…
侦探们
df
首先, 我们派出第一位侦探 df
, 以确认被占用的硬盘.
df
给出的调查报告如下
根据 df
先生的报告, 我们确认被占用的磁盘为 /dev/xvda1, 其挂载目录为 /
du
接下来, 该 du
先生出场了, 他会帮我们找到那该死的大文件在哪目录下面的.
我们先看他的第一次报告.
嗯, 从 /
中减掉 /data
目录下的 6.7G. 还有 8.3G.
O_O’’’
du
!!!! 你玩儿我呢吧… df
已经明确除了 /data
, /
目录下应该还有 19G 文件. 是不是不想干了!!!
lsof
这时, lsof
主动站出来说话了: 逗逼攻城狮, 说不定是有进程在向已删除的文件写数据啊!
嗯~ 原来如此…杀掉这个 28239
这个 Python 进程后, 磁盘占用恢复正常
真相只有一个
-
首先, 在 Linux 系统下, 当一个程序以
写模式
打开一个文件后, 会在进程中保留一个文件描述符
, 以便进程对磁盘进行写操作.文件描述符
在/proc
文件系统下, 表现为一个软链接
, 只占用 64 个字节的空间. -
其次, 而在 Linux 的文件系统中, 我们看到的所谓文件只是一个叫
硬链接
的东西, 而且可以有多个硬链接
指向同一个文件(调..啊不,和ln
妹纸沟通过就知道). 当指向某一文件块的所有硬链接
被删除后, Linux 才会回收对相应磁盘空间的占用
而此次事件的原因, 正好是文件描述符
和硬链接
指向同一块磁盘空间造成的.
故事应该是这样发生的:
- Python 进程打开了
write.log
的文件描述符, 进行写操作. 但却忘记关闭其描述符 - Linux 上部署的定时清理程序开始工作, 清理掉了
write.log
文件最后一个硬链接 - 因为 Python 进程的文件描述符没有关闭, Linux 内核”不敢”回收这块已经没有硬链接的磁盘空间.
- 磁盘空间仍被占用, 但对应目录下却没有
文件
.
现场还原
呃, 实际上, 公司的开发语言使用的是 java. 而且, 解决问题时并没有及时截图什么的. 所以, 上面那些数据就是用Python
还原现场时的数据了.
这里再附上 Python 脚本.
如果不想写太多数据出来, 可以用下面这个版本
死循环的目的都是为了模拟文件描述符占用