转载:http://blog.csdn.net/xx123er/article/details/51656218
node
现象:删除log后df看空间未释放python
解决方案:1.rm删除文件后,用lsof | grep XXX 查找使用该文件的进程,kill进程便可当即释放空间。linux
2.更好的方法是使用echo " ">file命令在线清空该文件。服务器
具体缘由分析和具体命令使用请详细阅读以下内容:数据结构
复现现象:1.写一个python程序,从public.log不停的复制内容写文件abc.txtspa
2. 运行程序后,看当前路径下文件.net
3,查看空间和df占用,删除正在被写的文件abc.txt,再次查看空间占用指针
能够看到删除了文件,空间并无释放,反而还在增长。对象
4.查看是什么进程占用了该文件,有两个python进程占用了该文件,后面的(deleted)表示该文件是已删除的blog
5.杀掉进程后,空间当即释放
更好的解决办法:
上面复现的过程已经有最基础的解决方案,就是找到占用文件的进程,杀进程,删文件,此解决方案太过粗暴,有如下理由
理由一:服务器中某些打log的进程是不能随意删除。
理由二:某个文件可能被多个进程占用,或者几十个进程占用,想释放空间就得杀掉因此进程。
解决方案二:采用将该文件置空的办法,执行echo " " >abc.txt
该方案能够在线清空log,但亲测执行时间过长,多是我每秒写600m的进程太特殊致使。须要权衡,若能够等或者进程不能停,就采用此方法,不然就采用kill进程的方法。
缘由探索:
Linux下文件的存储机制和存储结构:
一个文件在文件系统中的存放分为两个部分:数据部分和指针部分,指针位于文件系统的meta-data中,数据被删除后,这个指针就从meta-data中清除了,而数据部分存储在磁盘中,数据对应的指针从meta-data中清除后,文件数据部分占用的空间就能够被覆盖并写入新的内容,之因此出现删除abc.txt文件后,空间还没释放,就是由于python进程还在一直向这个文件写入内容,致使虽然删除了abc.txt文件,但文件对应的指针部分因为进程锁定,并未从meta-data中清除,而因为指针并未被删除,那么系统内核就认为文件并未被删除,所以经过df命令查询空间并未释放也就不足为奇了。
在文件系统处理文件须要的信息都存放在索引节点(inode)中,若是在删除文件的时候索引节点的引用计数不为0(表示文件正在被使用),则不会在磁盘中真正的删除文件,从而保证正在使用此文件的进程可以正常的处理文件。
首先咱们一块儿来看一下内核中关于文件系统的一些关键数据结构的关联,当一个进程打开一个文件后,便会在内核中建立一个file对象,这个对象主要描述了进程如何与文件进行交互。file对象中将指向一个dentry结构(目录项),目录项中描述了目录项名称,父目录项信息,子目录项信息等。而dentry中的d_inode所指向的inode节点中则包含了实际的文件存储在磁盘上的信息。
当多个进程打开同一个文件时,内核中变会建立相应的file对象,可是他们都公用同一个dentry,只不过每一次打开文件dentry的引用计数d_count加1。而且对于打开的同一个文件而言,inode也是惟一的,inode的引用计数i_count通常为文件硬连接的数目。
验证上述说明:
1.后台往abc.txt写的脚本没停,继续写,将文件重命名为abc.log
2.删除重命名后的文件
3.删除后用df命令发现所占空间没有减少,查看占用进程发现abc.txt没有进程占用,重命名后的abc.log有进程占用,说明重命名该文件,但inode并无改变,linux经过inode来查找对应文件,因此继续往重命名后的文件写入。
Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来讲,文件名只是inode号码便于识别的别称或者绰号。表面上,用户经过文件名,打开文件。实际上,系统内部这个过程分红三步:首先,系统找到这个文件名对应的inode号码;其次,经过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。