今天有个实习生问了我一个奇怪的问题,“离线32G磁盘大小的开发机(虚拟机)无法打印日志”,所以跟大家分享一下跟踪的过程。画外音:你们开发机的磁盘容量有多大?先du,查看磁盘空间:[shenjian@dev02~]#du-sch/16G/画外音:好像还有空间。再次尝试df,发现结果不一样:[shenjian@dev02~]$df-hfilesystemcapacityusedavailableavailable%mountpoint/dev/sda233G33G33G100%//dev/sda1965M30M886M4%/bootvoiceover:display32Gareall用光。du:diskusage搜索文件计算每个文件的大小,然后将结果值相加。df:diskfree通过文件系统获取空间大小信息。如果用户删除了正在运行的应用程序打开的目录中的文件:du命令返回的值显示减去文件后的总大小df命令返回的值不显示减去的文件最终大小(文件句柄仍在使用中),直到运行的应用程序关闭打开的文件(空间不会真正释放)。一个常见的场景是删除一个正在写入的大tomcat访问日志,du显示的结果会减去日志大小,而df仍然会包含日志的大小(实际上tomcat还是指文件的句柄)。给我们的启示是,如果要删除某条访问日志,不要暴力rm,要温柔:echo"">access.log画外音:朋友,你有没有rmed过一个还被引用的日志?如何发现它被使用了引用“已删除”文件的程序呢?lsof:listopenfiles使用lsof查看打开的文件。lsof|的结果grepdeleted显示我的一个logsvr程序(跑了几个月)和一个实习生写的web-server程序(实习大作业)处于删除状态,很可疑。画外音:请将手机上的图片放大。最后发现是其中一个web-server程序:while(pid=fork())是手写的:while(pid==fork()),导致fork进程一直停留在whileuntil系统资源耗尽。并且进程已经变成了僵尸进程,杀不死。重启开发虚拟机后,问题解决。画外音:放开我,多了一个等号,这个bug太真实了。一分钟不长,希望你有所收获:du:diskusagedf:diskfreelsof:listopenfilesecho"">access.log在这里,多看看作者的好文章
