Linux系统home磁盘空间占用过大

本文发布时间: 2019-Mar-22
昨日线上一台机器上的nginx rt飙高,@明俨 调查发现这台机器上的metaserver内存占用很高,同时还有个奇怪的现象,df发现/home的空间占用在增长飞快,但metaserver和nginx的日志文件增长都很慢,通过du -sh /home统计home下文件的总大小,发现跟df命令/home占用的空间小10+g,到底谁占用了我的磁盘空间?后来把nginx进程都停掉后(当时应该先通过lsof或/proc/pid/fd/看看nginx当时打开的文件情况),df显示/home的空间一下降下来了,跟du统计的结果能匹配上,说明这些磁盘空间都被nginx进程占用着。内核组的同事告诉我们,一个文件被进程打开后,在关闭前如果文件被删除,此时这个文件已经在它父目录的目录项中被删除掉(在父目录ls已经看不到这个文件),但该进程依然能够正常的读写文件,直到文件被该进程关闭后,这个文件的空间才会被回收,通过下面一个小例子解释下。int main(){ int fd = open("afile", O_CREAT | O_RDWR); assert(fd > 0); unlink("afile"); while (1) { char buf[1024]; // 1K for (int i = 0; i < 102400; i++) { int len = write(fd, buf, 1024); assert(len == 1024); } lseek(fd, 0, SEEK_SET); // keep writing, but don't make it increase sleep(5); } return 0;}# g++ filetest.cpp# lsa.out filetest.cpp 没有afile这个文件# du -sh 16K .# df -m | grep home /dev/sda9 639406 521255 85148 86% /home# ./a.out & 执行测试程序,持续写文件前100M的空间# lsa.out filetest.cpp 没有afile这个文件# du -sh 16K .# df -m | grep home/dev/sda9 639406 521355 85048 86% /home# killall a.out 杀掉测试程序# df -m | grep home /dev/sda9 639406 521255 85148 86% /home可以看出,进程在打开afile之后立即unlink掉这个文件,通过ls看不到这个文件,因为父目录中这个文件的信息已经删除,在进程持续写文件的过程中(为了避免空间暴增,一直写前100M,仅供测试观察之用),通过du -sh发现该目录下文件总空间没有变化,因为du是通过遍历文件来统计的,而通过df我们发现home的used刚好增加了100M的空间,接下来我们把测试程序关闭掉,home的used又降了100M,说明afile的空间已经被回收了。nginx有个特性,post请求的body如果超过2个page(可配置),就会把body的数据写到磁盘暂存,等请求处理完后,再删除临时的文件。nginx在open创建临时文件后,会先unlink掉这个文件(为什么要这么做,有什么好处?),然后在请求处理完后close掉文件。告警的服务器当时由于metaserver占用了大部分的内存,已经出现了swap的情况,而通过nginx写的文件平均大小在60-70K左右,基本都要写临时文件,导致nginx的服务越来越慢,积压大量的POST请求,这些请求对应的临时文件一直占用着磁盘空间,但因为文件已经删除,外面已经看不到这些文件的存在,从而导致du,df显示的结果相差很大。


(以上内容不代表本站观点。)
---------------------------------


2019-Mar-25 01:02am
栏目列表