07 2015
18

Linux系统奇怪的磁盘占用解决记录
2015年07月18日

近日我所维护的一台服务器运行出现了异常,翻开程序运行日志,初步发现问题是某个过程无法创建新临时文件。 再仔细阅读日志,看到了Java报出的Java.io.IOException; there is not enough space on the disk

那么问题就很明显了,磁盘占满了。但是这事本身就让我很费解,因为这个服务器上所跑的程序不会长期存储文件, 只是一个数据加工服务器,把传入的文件进行一定的处理然后再回传,期间会产生一些临时文件,但都会在处理 过程结束后自动删除掉。我第一想到的就是,会不会是这个自动删除的功能没做好,导致临时文件堆积如山, 但是经过检查,包括系统其他程序在内所产生的临时文件不到1G,根本不足以占满系统。

我运行df命令查看磁盘的占用情况,看到了4个磁盘挂载点,发现是挂载在/上的磁盘总共50GB被占满了。 于是我在根目录运行du -h -x --max-depth=1想看看是哪个目录占用的这么多空间,我好判断到底出什么问题了, 这个命令中的-x参数会让du命令不统计不在同一个磁盘分区上目录,或换句话说,忽略其他的磁盘挂载点。 结果令人崩溃,根本不用看哪个目录有问题,整个根目录总共统计,磁盘只占用了5.5GB。 那么50GB的磁盘被占满了,但是实际统计磁盘上的文件,总共却只有5.5GB大小,那么剩余的44.5GB被什么鬼用掉了?

我只好进行我的Google功课,然后认识到了几点非常重要的Linux特性。这个特性我以前也知道,却没有重视。 就是在Linux的文件系统中删除一个文件,系统并不会真的立刻把这个文件丢弃掉,而只是把它从文件的目录系统中移除, 只有确保所有使用这个文件的程序全部都退出后,才会真的把文件彻底删除掉。所以这些幽灵文件还会占用磁盘空间, 不过这些幽灵文件并不会出现在df命令的统计中去,因为它们已经不存在于任何目录当中了。

文件系统作为Linux最核心的部件,工具也是最齐全的。lsof此时就可以针对此问题进行检查了,这个命令是用来 列出整个系统中所有被打开的文件(顺便还可以查看所有已经启动的硬件设备以及打开的网络连接等)。 已经从目录系统中移除,但任然被程序占用的的文件可以用lsof | grep '(deleted)'来查看。 经此我立刻就发现了我的问题在哪里了:有一个已经被“删除”掉的日志文件,因为并没有关闭或重启程序, 该文件还在一直被使用着,还在忠实地记录着程序的运行状态。该程序已经持续运行半年了,而且日志文件一直都是 以同一个文件打开描述进行操作(日志文件只在程序开始时打开过一次,后面一直用这个打开的文件), 这个日志文件已经涨到40多GB了。

找到问题后,解决就简单了,我重启了那个程序,立刻40多G的占用空间就归还给了系统,所有程序都运行正常了。 当然这只是权宜之计,解决眼前问题采取的快速措施。要根除此问题就要用更科学的方式记录日志,使用已经成熟的 日志系统是个比较正确的选择。