磁盘满了,先别急着删日志
服务器磁盘告警,/var 分区用到 92%。当时第一反应是清日志,进 /var/log 把几个老文件删掉,前后删了快 2G。回到监控页一看,使用率纹丝不动,还是 92%。
问题出在删除方式上。日志文件被删掉的时候,写日志的进程还开着这个文件句柄,文件名没了,数据块不会释放,空间要等进程退出或者重新打开日志才回来。查这个有个现成命令:
lsof +L1 | grep deleted
输出里能看到哪个进程还占着已删除的文件,后面跟着实际占用的大小。确认之后,把那个服务平滑重载一下,让它重新打开日志文件,空间立刻就回来了。后来几次遇到 df 和 du 对不上的情况,基本都是这个原因:du 按文件名统计,文件已经没名了,自然统计不到;df 看的是文件系统实际占用,句柄没放,占用就还在。
还有一种满法更容易误判。df -h 显示还有十几 G 空闲,应用却报 No space left on device 写不进去。这种情况多半是 inode 用完了,要用 df -i 看。小文件特别多的目录最容易吃 inode,比如缓存和会话文件这类目录,还有那种一次解压出几万个小文件的临时目录。处理办法只能删文件腾 inode,或者把这类目录迁到单独挂载点,别无他法,扩容磁盘没用。
日志本身为什么涨这么快,也顺手查过几次。常见就两个原因。一个是某个服务调试时开了 debug 级别,上线忘了关,一天能写好几个 G。另一个是 logrotate 配置只按天切分、保留份数又多,日志量一涨,切分跟不上,保留的总量也跟着失控。后来把几个大户改成按大小切分,单个文件 200M 切一次,保留 10 份封顶,总量算得出来,心里有数。
再后来给自己定了个简单顺序,磁盘告警先跑这三条,再决定动什么:
df -h df -i du -x --max-depth=1 /var | sort -n
第一条看空间,第二条看 inode,第三条找大户。三条跑完,满的原因大半能定位。实在定位不了,再去看 lsof 的 deleted 列表。
另外一个小调整:告警阈值从 95% 提前到 80%。95% 才报,留给处理的时间太短,半夜被叫醒不说,日志还在涨,删慢了就直接写满出故障。80% 报警,工作时间就能处理掉,多数时候就是清一批过期文件的事。
删日志这个动作本身没错,错在没看清满的原因就动手。空间没释放、inode 满了这两种情况,删再多日志都不解决问题,先定位再处理,花的总时间反而更少。
- 点赞
- 收藏
- 关注作者
评论(0)