文件已删除但不释放的原因

错误现象

运维监控系统传来通知,报告一台服务器空间满了,经过查询根分区确实没有空间。
由于linux没有回收站的功能,所以服务器上删除的文件都会先移动到/tmp下,所以要定期清理/tmp下的文件。下面先检查/tmp下最大的三个数据文件。

[root@homjun ~]# du -sh /tmp/* | sort -nr | head -3
66G    /tmp/access_log
36k     /tmp/hsperfdata_root
36k     /tmp/hsperfdataa_mapred

通过命令输出发现在/tmp目录下有66G大小的文件,这个文件是由Apache产生的访问日志文件,从日志大小来看,应该是很久没有清理Apache日志文件了。

[root@homjun ~]# rm -rf /tmp/access_log

接着查看系统根分区空间是否释放

[root@homjun ~]# df -h

发现并没有释放,这是为什么呢?

一个文件在文件系统中的存放被分为两个部分:数据部分和指针部分,指针位于文件系统的meta-data中,在讲数据删除后,这个指针就从meta-data中清除了,而数据部分存储在磁盘中。在将数据对应的指针从meta-data中清楚后,文件数据部分占用的空间就可以被覆盖并写入新的内容。之所以在出现删除access_log文件后,空间还没有释放,就是因为httpd进程还在一直向这个文件写入内容,导致虽然删除了access——log文件,但是由于进程锁定,文件对应的指针部分并未从meta-data中清除,而由于指针并未删除,系统内核就认为文件并未删除,因此通过df命令查询空间并未释放也就不足为奇了。

问题排查

接下来看看是否有进程一直在向access_log文件中写数据,这里需要用到linux下的losf命令,通过这个命令可以获得一个仍然被应用占用程序占用已删除文件列表,命令执行如图所示。

lsof | grep delete
httpd    2986    apache    3w    REG    8    70866960384    75694218  /tmp/access_log(deleted)

从输出的结果可以看到,/tmp/access_log 文件被进程httpd锁定,而httpd进程还一直在向这个文件写入数据。从第7列所知这个文件大小70G,我滴鬼鬼...最后一列"deleted"状态说明这个日志文件已经被删除,但是进程还在一直向此文件写数据,因此空间未被释放。

解决问题

方法有很多种:

  1. 关闭或者重启httpd进程
  2. 重启操作系统
    这些都不是最好的方法,对待这种进程不停对文件写日志的操作,要释放文件占用的磁盘空间,最好的方法就是
  3. 在线清空这个文件,具体命令如下:
[root@homjun ~]# echo " " > /tmp/access_log

通过这种方法,磁盘空间不但可以马上释放,也可以保障进程继续向文件写入日志,这种方法经常用于在线清理Apache、Tomcat、Nginx等Web服务产生的日志文件。

原文地址:https://www.cnblogs.com/homjun/p/15073904.html