使用du与df命令查看磁盘容量不一致
问题现象
在 Linux 系统的运行过程中,会经常遇到磁盘使用率过高,通过执行 du 与 df 命令查看磁盘容量确出现不一致的现象,例如以下几种现象:
- 执行 du 和 df 命令显示的结果不一致,df 比 du 命令显示的数据大很多。
- 使用 df 命令显示磁盘使用率过高,但是执行 du 命令统计目录时却磁盘使用率不高,且查不到已删除的句柄文件。
- 当前系统存在数据盘挂载点,使用 df 命令查看系统盘容量已满,但是在根目录下使用 du 命令统计各文件总容量,但是合计达不到总容量。
原因分析
首先了解下 du 和 df 的工作原理:
du 命令会对待统计文件逐个调用 fstat 这个系统调用,获取文件大小。它的数据是基于文件获取的,所以有很大的灵活性,不一定非要针对一个分区,可以跨越多个分区操作。如果针对的目录中文件很多,du速度就会很慢了。
df 命令使用的事 statfs 这个系统调用,直接读取分区的超级块信息获取分区使用情况。它的数据是基于分区元数据的,所以只能针对整个分区。由于 df 直接读取超级块,所以运行速度不受文件多少影响。
其次,出现du和df统计的值有较大偏差时,主要会有以下几种原因:
-
用户删除了大量的仍在使用的文件后,du 命令不会在文件系统目录中统计这些文件。因为这个已经被删除的文件句柄不会真正在磁盘中被删除,分区超级块中的 inode 信息不会更改,df 命令仍会统计这个被删除的文件。 此时可通过 lsof 命令查询处于 deleted 状态的文件,被删除的文件在系统中被标记为 deleted。如果系统有大量 deleted 状态的文件,会导致 du 和 df 命令统计结果不一致。
-
当用
du -sh *
命令来统计某个目录总容量时,如果该路径下包含隐藏文件,是不会包含在统计结果里的。 -
由于数据盘挂载前该路径下就存在文件,挂载后用 du 无法查询到原路径下文件大小。
处理建议
- 先通过
lsof|grep delete
查询目标目录下是否有被标记为已删除的文件,如有通过重启该文件所使用的进程可释放空间。(如是日志类文件,在暂时无法重启程序的情况下,也可通过进入/proc/进程ID/fd
目录下,找到删除的文件,然后执行情况命令,可临时释放空间的问题。) - 在目标目录下,执行
du -ah
命令统计结果中看是否包含较大的隐藏文件。 - 排除了1和2的原因检查后仍未解决问题,考虑可停业务应用,卸载数据盘后再次使用 du 命令查询,看是否定位到原因。
- 以上排除均未找到问题,建议对所有应用程序进行一个停止,观察是否有释放,从而进行进一步定位。
- 一时半会找不到原因的,也可通过扩容文件系统,先降低高水位情况, 再持续分析,毕竟扩容也只是治标不治本。
示例:
通过运行
ls -l /proc/3351/fd/* | grep caist-admin
找到相应文件句柄
然后通过 echo "" > /proc/3351/fd/{FD_NUM}
清空文件