记一次/tmp空间泄露问题定位

一、问题概述

部分服务器在长时间运行后出现了/tmp空间告警(大约半年)
在这里插入图片描述
磁盘空间占用过高时因为我们部署的进程占用了/tmp下已删除的文件,导致文件并没有真正释放,并且进程在持续写文件。这实际上是一种句柄泄漏。可以通过命令查看:

lsof |grep -i del|grep tmp

在这里插入图片描述
可以看到被占用的文件以及占用进程。可以确认这种文件不是进程中主动打开的文件,而是linux在某种机制下创建的临时文件。解决这个问题,最直接的办法是重启所有占用了此文件的进程,如上图的进程59613,但这种做法代价太大。根本的解决方案是优化代码,找到可能泄漏资源的地方。

二、临时解决方案

临时有个相对优雅的解决方案,可以清掉文件内容,解决空间告警。进程所打开的所有文件,在/proc/PID/fd/下均有记录(即文件描述符),linux的机制是允许删除被进程占用的文件,但只有所有进程解除占用后才会真正释放空间(这一点与windows不同,windows不允许删除被占用的文件)。因为/tmp下文件已经被删除了,所以无法按文件路径和文件名清空,但是因为进程下打开的文件描述符还在,所以可以通过清文件描述符的方式清空这个文件。
echo > /proc/PID/fd/FD
或者
truncate -s 0 /proc/PID/fd/FD
其中PID和FD是变量,需要根据实际情况填写。方法如下:

命令lsof展示的各列内容为:
在这里插入图片描述
在这里插入图片描述

三、根因定位

即然我们能根据文件描述符清空该文件,我们也能查看该文件的内容:
tail -f /proc/PID/fd/FD
然后发现,文件内容全部是上述进程59613打印的日志!查看代码,日志打印全部采用的标准syslog打印,不可能出现这种泄漏。然后通过写dome测试、逐步缩小范围等等措施,最后发现是自动启动脚本导致的问题。内容如下:
nohup ./program -param &
我们使用nohup(no hang up)命令将进程扔到后台执行。如果我们没有对进程的打印信息进行重定向,nohup指令则会在进程路径下创建一个nohup.out文件用于输出进程的打印信息。

同时,我们为了让进程具备故障自动恢复的能力,将这个启动脚本交给了corntab定时执行。实测发现,当脚本手动执行时,会在进程路径下创建nohup.out文件,当脚本由crontab执行时不会创建这个文件,而问题就出现在这里!当没有nohup.out文件时,linux操作系统会将这部分打印在tmp空间创建一个临时文件,然后输出,而tmp下的文件会被tmpwatch定时删除。但是因为进程还在不停打印日志,这个临时文件尽管已经被删除但是句柄并没有被进程释放,最终就会导致tmp空间泄漏!

所以最终的解决方案是对进程日志进行重定向
nohup ./program -param >/dev/null 2>&1 &
注:即是将日志扔进黑洞设备,同时标准错误输出重定向到标准输出。日志扔进黑洞设备是没有关系的,进程中使用syslog标准打印还是会打印到syslog中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值