今天早上收到一个报警,测试服务器磁盘使用量100%,然后我着急忙慌的赶快去处理了。
先看具体每个挂载磁盘使用量

df -h

发现/opt 目录挂载磁盘满了。

第一反应是估计是cdh里面的组件或者开发的拦截器之类的写log写满了,于是去opt目录下具体看是那个文件夹出了问题

du -h --max-depth=1 /opt/

然后尴尬的一幕出现了,du 命令显示 opt整个目录一共占用 69G

而df 目录提示占用 985G 100%

于是我找了下df于du命令实现原理。。。

du 的工作原理

du 命令会对待统计文件逐个调用fstat这个系统调用,获取文件大小。它的数据是基于文件获取的,所以有很大的灵活性,不一定非要针对一个分区,可以跨越多个分区操作。如果针对的目录中文件很多,du速度就会很慢了。

df 的工作原理

df 命令使用的事statfs这个系统调用,直接读取分区的超级块信息获取分区使用情况。它的数据是基于分区元数据的,所以只能针对整个分区。由于df直接读取超级块,所以运行速度不受文件多少影响。

那么他们最大的区别就是一个是基于文件本身的,一个是基于分区元数据,他们两个统计不一致而去du统计数据小于df 就可以推导出 原因很大可能是某个文件删掉了所以du就不会再统计它了,但是分区元数据没有修改df所以继续做了统计。造成这个现象的大家很容易能联想到的就是某个程序还在占用这个已经被删除的文件的句柄,那么这样这个文件就不会真正的物理删除,所欲元数据还存在。。

一般处理方法

使用lsof命令找到还持有被删除文件句柄的进程,然后关闭进程或者杀掉进程用以释放空间。

lsof | grep deleted

处理方法一

kill -9 xxxx

处理方法二

可以使用清空文件的方式来代替删除文件,方式是:echo "" > xxx.log。

PS

除了rm外,有些命令会间接的删除文件,如gzip命令完成后会删除原来的文件,为了避免在出现这种问题,前先确认没有进程打开该文件