从对我的质疑说起,谈谈Linux下的文件删除
特特本来就是个刚毕业的小菜,很多知识都是靠着大家的指点才慢慢学会的。之前在一篇"纯属虚构"的文章 (鹅厂后台开发工程师的工作日常) 提到使用 rm
命令删除一个近 100 G 的 log 文件。
很荣幸,这篇文章被一个大号转载了,获得了很不错的阅读量。但是,当我看到有大佬在公众号留言,"质疑" 我文章内容的正确性,甚至把我个人的水平上升到了鹅厂程序员的水平高低问题时,我真是战战兢兢、瑟瑟发抖。
咱也不敢说,咱也不敢问,只能默默地去补习相关的知识,于是有了这篇文章。
一、Linux 删除文件的原理
通过查阅资料知道,Linux 系统下的文件被分成文件元数据 (metadata)和用户数据 (user data) 两部分。
用户数据,亦即文件数据块 (data block),是保存文件真实内容的空间;而元数据则是保存如文件大小、创建时间、所有者等文件的附加属性。
在 Linux 中,文件的元数据保存在一个 inode 结构中,inode 号是文件的唯一标识,而文件名仅是为了方便人们的记忆和使用。当然文件名与 inode 之间会存在映射关系。
而 inode 结构中与本文提到的文件删除相关的两个重要参数分别是:i_nlink 和 i_count。从 VFS 的 inode 结构体定义中可以看到其类型如下:
struct inode {...const struct inode_operations *i_op; // 索引节点操作unsigned long i_ino; // 索引节点号atomic_t i_count; // 引用计数器unsigned int i_nlink; // 硬链接数目...
}
当某个进程使用了文件时,该文件的 i_count 值会增加;当创建文件的硬链接 (区别于软链接)时,该文件的 i_nlink 值会增加。
当 i_nlink 和 i_count 均为 0 时,文件才会被真正删除 (这里的删除是指删除了文件名到 inode 之间的链接关系,而文件的内容仍然完好无损地保存在磁盘中。如果此时关闭机器,阻止任何新的写磁盘操作,那么被删除的文件理论上也是可以恢复的)。
而执行删除命令 rm
时,本质上只是减少了 (或置0) 该文件的磁盘引用计数 i_nlink。
换言之,如果被执行 rm
命令的文件正在被其他进程所引用,那么此时该文件对应的 i_count 将不为0,即便执行了 rm
操作,该文件并没有真正被删除,占用的磁盘空间也未被释放。
因此,上面截图中的评论是正确的,仅仅通过 rm
命令确实无法使用被进程打开的文件所占用的磁盘空间。
PS:为啥小特特在工作中可以直接通过 rm
删除和释放被进程使用的 log 文件呢?其实是因为通过脚本删除文件时会触发进程 reload 的逻辑,进程执行 reload 时会重新打开 log 文件 (当然会先关闭)。
二、Linux 删除大文件的几个简单方法
那么,Linux 下删除一个大文件的正确方式是什么呢?(假设待删除的大文件名为 access.log)
个人觉得最简单的方式是执行命令 > access.log
。通过重定向 null 到待删除的文件可以让该文件瞬间成为空白,有效地释放磁盘空间。
另外,cat /dev/null > access.log
命令也是一个不错的选择。/dev/null
是一个特殊的文件,它可以清空送到它这里来的所有输入,而它的输出则可被视为一个空文件。
echo -n "" > access.log
也是常用的一个命令。需要注意的是,别忘了加上 -n
选项 (否则 access.log 文件中会出现一个空白行)。
当然,还可以通过 truncate
命令将待删除的文件大小缩小为0,但是我平时用得很少。
三、Linux 进程打开的文件信息
再延伸下:
在 Linux 系统下,当进程打开一个文件后,内核会为该进程在 /proc/
目录下建立一个以该进程 pid 为名的文件夹来保存该进程的相关信息。而 /proc/pid/fd/
文件夹保存的就是该进程打开的所有文件的文件描述符 (file descriptor, fd)。
除了打开的本地文件,进程建立的 socket 链接也算是一个 fd。
一个进程打开的文件数量是有限的,执行 cat /proc/pid/limits | grep "Max open files"
命令可以查看进程号为 pid 的进程允许打开的最大文件个数。
当在 Linux 下调用 open 函数返回了系统错误码 24 时 (对应的系统错误描述是:"Too many open files"),则表示当前进程打开的文件数量超过了系统设置的上限。
如果你的程序遇到了这个错误,按我的经验来看,一般是出现句柄泄漏了 (可能是文件未正常关闭、socket 链接未正常断开等),这时候就需要你耐心地 debug 啦。
四、如何高效清空包含大量小文件的目录
再再延伸下:
Linux 下怎么快速地删除包含大量小文件的目录?
直接通过 rm -rf ./*
命令容易导致系统 I/O陡增。我一般使用的方法是利用 rsync
命令同步目录的机制,通过新建一个空目录,再将待删除的目录与新建的空目录进行同步,从而达到清空目录的目的。
从对我的质疑说起,谈谈Linux下的文件删除相关推荐
- Linux下对文件的操作及添加新用户
Linux下对文件的操作及添加新用户 一.对文件的操作 1.打包压缩文件 2.解压缩文件 3.对文件操作的其他命令 二.创建新用户 一.对文件的操作 1.打包压缩文件 2.解压缩文件 3.对文件操作的 ...
- linux下查看文件编码及修改编码
linux下查看文件编码及修改编码 查看文件编码 在Linux中查看文件编码可以通过以下几种方式: 1.在Vim中可以直接查看文件编码 :set fileencoding 即可显示文件编码格式. 如果 ...
- Linux下各文件夹的结构说明及用途介绍(转载)
linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...
- linux下查找文件及内容 grep
每一种操作系统都是由成千上万个不同种类的文件所组成的.其中有系统本身自带的文件,用户自己的文件,还有共享文件等等.我们有时候经常忘记某份文件放在硬盘中的哪个地方. 在微软的Windows操作系统中要查 ...
- linux中rm删除的文件是否可以恢复,Linux下用rm删除的文件的恢复方法
Linux下用rm删除的文件的恢复方法_Linux教程_Linux公社-Linux系统门户网站 https://www.linuxidc.com/Linux/2008-08/14744.htm lin ...
- linux 下创建文件的方法
linux 下创建文件的方法 touch aaa.txt 创建一个叫aaa.txt的文件 echo "" >> aaa.txt 创建一个叫aaa ...
- Linux下常见文件解压方法及命令
Linux下常见文件解压方法及命令时间:2007-01-08 18:34来源:CSDN作者:bitsCN编辑字体:[大 中 小]1.以.a为扩展名的文件: #tar xv file.a 2.以.z为扩 ...
- Linux下查看文件占用空间大小的du 和df 命令
Linux下查看文件占磁盘大小一般使用du或df命令 df命令:用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. du命令 ...
- Linux下对文件操作时出现乱码怎么办?
Linux下对文件操作经常会遇见乱码问题,我在网上搜了一些解决方法,希望能对大家有所帮助. 如果你需要在Linux中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中 ...
最新文章
- Oracle EXP-00091解决方法
- 用IP地址的用途理解Loopback接口
- Codeforces Round #297 (Div. 2)C. Ilya and Sticks 贪心
- python中dict和list排序
- HDU2206 IP的计算【文本处理】
- 自动驾驶 9-6: EKF 的替代方案 - 无迹卡尔曼滤波器
- 资本寒冬下一个有娃女码农--应聘高级Android工程师历程感言
- 布谷鸟算法浅谈与简单应用
- 企业级PHP发卡网源码,金发卡企业级发卡平台源码
- 2021-01-08
- nfs总结之工作原理
- 用python监控互联网网速
- 正态分布的应用——基于偏度系数解释发展水平
- 房贷要不要提前还款两种还款方式比较
- 以麒麟音乐为例,教你如何构建专属自己的音乐播放器
- Prim算法实现最小生成树(Java)
- 处理R安装后出现You're using a non-UTF8 locale, therefore only ASCII characters will work.的情况
- 【北亚数据恢复】Hp DL380服务器raid磁盘故障导致数据库数据丢失的数据恢复案例
- go实现NSQ消息队列的集群部署
- 弹指间计算机协会 2021“千里码”程序设计竞赛 题面