场景
“删了日志文件,磁盘空间纹丝不动?”运维工程师老王盯着屏幕上的df -h结果,陷入沉思。昨晚刚清理了/var/log下50G的应用日志,今天监控告警依旧:/dev/sda1分区使用率96%。他又敲了du -sh /var/log,显示仅2.3G。“这50G难道蒸发了?”
一、破案关键:df和du的“认知差异”
Linux系统中,df和du就像两个会计师,但查账方式截然不同:
- df:直接翻阅文件系统的“总账本”(inode表),只要inode存在(哪怕文件名已删除),就认定空间被占用
- du:挨家挨户清点“门牌”(文件名),只统计能找到门牌的文件
当进程打开文件时,系统会给它一把“钥匙”(文件句柄)。即使你删除了文件名(门牌),只要进程还握着钥匙(未关闭文件句柄),inode就不会被回收,这就是“僵尸文件”的由来。
二、侦探工具:lsof命令锁定“真凶”
想要找到这些隐形文件,lsof(list open files)是终极武器。执行以下命令:
lsof -nP | grep deleted | awk '{print $2,$10}'
输出可能如下:
1234 /var/log/app.log (deleted)
5678 /tmp/temp.db (deleted)
- 1234:占用文件的进程PID
- /var/log/app.log:已删除但被占用的文件路径
技巧:加上-sock参数排除网络连接,+L1只显示链接数为0的文件(已删除文件特征)
三、处置方案:给进程“断舍离”
找到PID后,有三种“解锁”方式(按安全等级排序):
- 温柔重启:systemctl restart app.service(推荐,适用于大部分服务)
- 优雅终止:kill -15 1234(给进程时间保存数据)
- 终极手段:kill -9 1234(紧急情况使用,可能导致数据丢失)
老王尝试重启应用服务后,再次执行df -h,/dev/sda1使用率瞬间降至42%——失踪的50G终于回来了!
四、永久防坑:给系统装“防盗门”
- 日志轮转配置(/etc/logrotate.d/app):
/var/log/app/*.log {
daily
rotate 7
compress
delaycompress
missingok
postrotate
/bin/kill -HUP `cat /var/run/app.pid 2>/dev/null` 2>/dev/null || true
endscript
}
- 进程监控脚本:
#!/bin/bash
# 磁盘使用率超85%时检查deleted文件
if [ $(df -h / | awk 'NR==2{print $5}' | cut -d% -f1) -gt 85 ]; then
lsof -nP | grep deleted > /tmp/deleted_files_$(date +%F).log
# 发送告警邮件
mail -s "磁盘空间异常" admin@example.com < /tmp/deleted_files.log
fi
- 服务开发规范:确保程序支持SIGUSR1信号重新打开日志文件(如Java的logback支持kill -USR1 PID)