CentOS 6.9下du显示目录占15GB但实际文件仅32MB的问题排查
问题分析与解决思路
结合你在CentOS 6.9上碰到的这个Jenkins相关的磁盘空间异常问题,我梳理了几个最可能的原因,以及对应的验证和解决方法:
1. 目录项存在但文件名含特殊字符,导致ls显示异常
这是最符合你描述“ls -lha仅显示几个文件,但vim ..能看到7500+文件”的核心原因。
Jenkins的解压脚本在创建临时目录时,可能因为脚本变量错误、时间戳生成异常等问题,导致生成的目录名包含了不可打印控制字符(比如换行符、空字符、退格符):
ls在输出时,这些特殊字符会破坏输出格式,比如换行符会让一个目录名被拆成多行显示,看起来像是几个零散文件;或者某些字符会导致ls输出被截断,让你看不到真实的文件数量;- 而
vim在浏览目录时,会自动将这些特殊字符转义成可见形式(比如用^J表示换行符),所以能正确显示所有7500+个解压目录; du -ahx是直接遍历磁盘inode统计空间,不受文件名特殊字符影响,所以能准确统计出15GB的总占用,以及每个解压目录66MB的大小。
验证方法:
执行下面的命令统计符合命名规则的目录数量,应该能得到和vim看到的接近的数字:
find . -type d -name "schemajs-*" | wc -l
或者用-print0参数处理特殊字符,查看真实的目录列表:
find . -type d -name "schemajs-*" -print0 | xargs -0 ls -ld
2. 已删除但被进程占用的临时文件(Unlinked Files)
如果上面的验证不成立,那就要考虑这个经典的Linux磁盘空间异常场景:
Jenkins的构建脚本可能已经删除了这些解压目录,但某个进程(比如解压工具的子进程、Jenkins的构建代理进程)还在持有这些目录下文件的打开句柄。Linux系统中,只要有进程打开文件,即使目录项被删除,磁盘空间也不会被释放:
du统计的是磁盘实际被占用的块,所以会把这些“隐形”空间算进去;ls看不到这些文件,因为它们的目录项已经被删除;- 这种情况下
vim ..也看不到这些目录,所以如果你的vim ..确实能看到目录,这个原因可能性较低,但也可以排查。
验证方法:
执行下面的命令,查看是否存在未释放的文件句柄:
lsof | grep deleted | grep schemajs
解决方法
针对上面的两种情况,分别对应不同的处理方式:
针对特殊字符文件名的情况
用不受特殊字符影响的命令删除这些目录:
# 递归删除所有以schemajs-开头的目录 find . -type d -name "schemajs-*" -exec rm -rf {} + # 或者用print0避免特殊字符问题,更稳妥 find . -type d -name "schemajs-*" -print0 | xargs -0 rm -rf
针对进程占用未释放的情况
- 用
lsof找到对应的进程PID,然后终止进程:
# 找到进程PID并终止 lsof | grep deleted | grep schemajs | awk '{print $2}' | sort -u | xargs kill -9
- 进程终止后,磁盘空间会自动释放,再用
du -ahx .验证即可。
长期预防建议
- 给Jenkins安装Workspace Cleanup插件,配置构建后自动清理临时文件和目录;
- 在Jenkins构建脚本中,添加
trap命令确保脚本异常退出时也能清理临时目录:
# 在脚本开头定义清理函数 cleanup() { rm -rf "${TEMP_DIR}" } # 绑定退出信号,确保脚本无论正常/异常退出都会执行清理 trap cleanup EXIT INT TERM
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

