1 问题
今天查看服务器磁盘空间,发现磁盘占用达到了98%,所以看了一下日志文件目录的磁盘占用情况,发现有很多的sql日志文件很大,在10G以上,所以准备清理一下,一开始准备清理60天之前的日志,后来发现,清理完了,还是不行,磁盘空间还是占用98%,但是日志文件是真的被删了,今天分享一下这个事情的原因以及解决办法。
1 | //查看Linux整个系统的磁盘空间命令 |
2 原因分析
在Linux上,每个文件都有一个自己对应的索引节点即inode,在这个inode里记录了文件在磁盘的块信息,以及链接数量等信息,一个文件在是否要被真正删除释放空间,取决于两个值,一个是i_count,代表引用计数;一个是i_nlink,代表硬链接数量,只有当两个都为0,文件才会真正释放。
当有进程使用该文件时候,i_count就会加1,当进程不在引用或进程结束,就会减一。
硬链接也是如此,当为文件创建一个硬链接时,i_nlink就会加一,删除就会减一,当减少为0时候,就会删除文件,释放空间。
可以通过以下命令查看文件被那些进程引用:
1 | $ lsof | grep deleted |
在Linux中,硬链接指的是文件名与inode的链接,通常创建一个文件对应一个硬链接,我们可以手动通过ln命令或者程序触发link系统调用为一个文件创建一个硬链接,相当于两个文件名对应了同一个磁盘文件,两个都删除才会删除磁盘文件(没有进程引用的前提下)。而Linux的rm命令相当于执行了unlink系统调用,会使得i_nlink数量减一。
当然,由于文件并没有被真正删除,所以该文件是可以恢复的,只需要找到进程的pid,并进入/proc/{pid}/fd中,找到对应的文件描述符,执行cp命令复制即可找回文件。
3 解决办法
3.1 杀进程
通过lsof
命令查看被删除的文件的被那些进程所引用,然后kill
掉这些进程即可,但是,这样做会有风险,如果这个进程是某个很重要的进程,那么会造成其他的问题,谨慎杀进程。
3.2 文件重定向
使用如下命令将一个很大的日志文件的空间释放掉:
1 | $ echo "" > log.log |
注意:
- 这里需要注意,不要使用
>>
,两个尖括号是追加的意思,一个尖括号才是覆盖写入。- 而且如果已经使用
find /data/logs -type f -name "*log*" -mtime +40 -exec rm {} \;
将某些文件删除了,那就只能等到对应进程释放该文件的资源了,不能再用这种方式释放空间,因为原来的文件已经不存在了,如果还使用该命令,则会重新创建一个新的文件,而原来的文件并没有释放
Reference
写在最后
欢迎大家关注鄙人的公众号【麦田里的守望者zhg】,让我们一起成长,谢谢。