特特本来就是个刚毕业的小菜,很多知识都是靠着大家的指点才慢慢学会的。之前在一篇"纯属虚构"的文章 (鹅厂后台开发工程师的工作日常) 提到使用 rm 命令删除一个近 100 G 的 log 文件。

很荣幸,这篇文章被一个大号转载了,获得了很不错的阅读量。但是,当我看到有大佬在公众号留言,"质疑" 我文章内容的正确性,甚至把我个人的水平上升到了鹅厂程序员的水平高低问题时,我真是战战兢兢、瑟瑟发抖。

咱也不敢说,咱也不敢问,只能默默地去补习相关的知识,于是有了这篇文章。

一、Linux 删除文件的原理

通过查阅资料知道,Linux 系统下的文件被分成文件元数据 (metadata)和用户数据 (user data) 两部分。

用户数据,亦即文件数据块 (data block),是保存文件真实内容的空间;而元数据则是保存如文件大小、创建时间、所有者等文件的附加属性。

在 Linux 中,文件的元数据保存在一个 inode 结构中,inode 号是文件的唯一标识,而文件名仅是为了方便人们的记忆和使用。当然文件名与 inode 之间会存在映射关系。

而 inode 结构中与本文提到的文件删除相关的两个重要参数分别是:i_nlinki_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_nlinki_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下的文件删除相关推荐

  1. Linux下对文件的操作及添加新用户

    Linux下对文件的操作及添加新用户 一.对文件的操作 1.打包压缩文件 2.解压缩文件 3.对文件操作的其他命令 二.创建新用户 一.对文件的操作 1.打包压缩文件 2.解压缩文件 3.对文件操作的 ...

  2. linux下查看文件编码及修改编码

    linux下查看文件编码及修改编码 查看文件编码 在Linux中查看文件编码可以通过以下几种方式: 1.在Vim中可以直接查看文件编码 :set fileencoding 即可显示文件编码格式. 如果 ...

  3. Linux下各文件夹的结构说明及用途介绍(转载)

    linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...

  4. linux下查找文件及内容 grep

    每一种操作系统都是由成千上万个不同种类的文件所组成的.其中有系统本身自带的文件,用户自己的文件,还有共享文件等等.我们有时候经常忘记某份文件放在硬盘中的哪个地方. 在微软的Windows操作系统中要查 ...

  5. linux中rm删除的文件是否可以恢复,Linux下用rm删除的文件的恢复方法

    Linux下用rm删除的文件的恢复方法_Linux教程_Linux公社-Linux系统门户网站 https://www.linuxidc.com/Linux/2008-08/14744.htm lin ...

  6. linux 下创建文件的方法

    linux  下创建文件的方法 touch  aaa.txt    创建一个叫aaa.txt的文件 echo   ""  >>  aaa.txt    创建一个叫aaa ...

  7. Linux下常见文件解压方法及命令

    Linux下常见文件解压方法及命令时间:2007-01-08 18:34来源:CSDN作者:bitsCN编辑字体:[大 中 小]1.以.a为扩展名的文件: #tar xv file.a 2.以.z为扩 ...

  8. Linux下查看文件占用空间大小的du 和df 命令

    Linux下查看文件占磁盘大小一般使用du或df命令 df命令:用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. du命令 ...

  9. Linux下对文件操作时出现乱码怎么办?

    Linux下对文件操作经常会遇见乱码问题,我在网上搜了一些解决方法,希望能对大家有所帮助. 如果你需要在Linux中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中 ...

最新文章

  1. Oracle EXP-00091解决方法
  2. 用IP地址的用途理解Loopback接口
  3. Codeforces Round #297 (Div. 2)C. Ilya and Sticks 贪心
  4. python中dict和list排序
  5. HDU2206 IP的计算【文本处理】
  6. 自动驾驶 9-6: EKF 的替代方案 - 无迹卡尔曼滤波器
  7. 资本寒冬下一个有娃女码农--应聘高级Android工程师历程感言
  8. 布谷鸟算法浅谈与简单应用
  9. 企业级PHP发卡网源码,金发卡企业级发卡平台源码
  10. 2021-01-08
  11. nfs总结之工作原理
  12. 用python监控互联网网速
  13. 正态分布的应用——基于偏度系数解释发展水平
  14. 房贷要不要提前还款两种还款方式比较
  15. 以麒麟音乐为例,教你如何构建专属自己的音乐播放器
  16. Prim算法实现最小生成树(Java)
  17. 处理R安装后出现You're using a non-UTF8 locale, therefore only ASCII characters will work.的情况
  18. 【北亚数据恢复】Hp DL380服务器raid磁盘故障导致数据库数据丢失的数据恢复案例
  19. go实现NSQ消息队列的集群部署
  20. 弹指间计算机协会 2021“千里码”程序设计竞赛 题面

热门文章

  1. px,em,rem,vw单位在网页和移动端的应用
  2. FFT算法的完整DSP实现(转)
  3. 从服务器上的数据库备份到本地
  4. title与h1标签的区别和联系
  5. SQL server 2000安装时提示我”以前的某个程序安装已在安装计算机上创建挂起的文件操作....”...
  6. 在VSCode Remote环境下开发Teams Bot
  7. Jmeter录制app脚本
  8. VS2010下的多线程窗口
  9. iOS-数据持久化-偏好设置
  10. 《WinForm开发系列之控件篇》Item1 BackgroungWorker