linux删除文件后空间未释放

来源:互联网 发布:斗龙战士1木拉多淘宝 编辑:程序博客网 时间:2024/05/21 07:51

现象:删除log后df看空间未释放

解决方案:1.rm删除文件后,用lsof | grep XXX 查找使用该文件的进程,kill进程即可立即释放空间。

                  2.更好的方法是使用echo " ">file命令在线清空该文件。

具体原因分析和具体命令使用请详细阅读如下内容:

复现现象:1.写一个python程序,从public.log不停的复制内容写文件abc.txt

                      

                 2. 运行程序后,看当前路径下文件

                   

                3,查看空间和df占用,删除正在被写的文件abc.txt,再次查看空间占用

                   

               可以看到删除了文件,空间并没有释放,反而还在增加。

               4.查看是什么进程占用了该文件,有两个python进程占用了该文件,后面的(deleted)表示该文件是已删除的

                   

             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,读出数据。

1 0
原创粉丝点击