由一次磁盘告警引发的“血案”——你知道 du 和 ls 区别吗?

来源 | 程序猿石头

责编 | Carol

封图 | CSDN下载自视觉中国

图来源于 SkyPixel

知道为什么会有上面的结果吗?什么又是稀疏文件?这篇文章将为你揭秘。

问题背景

确切地说,不是收到的自动告警短信或者邮件告诉我某机器上的磁盘满了,而是某同学人肉发现该机器写不了新文件才发现该问题的. 说明我司告警服务还不太稳定 :)

第一次出现该问题时,我的处理方式是:先删了 /tmp/ 目录, 空闲出部分空间,然后检查下几个常用的用户目录,最终发现某服务A的日志文件(contentutil.log)占用了好几个大G,询问相关开发人员后确定该日志文件不需要压缩备份,所以可直接删除, 于是 rm contentutil.log 之后就天真地认为万事大吉了…(不懂为啥当初没 df 再看看)

然而大约xx天后,发现该机器磁盘又满了,惊呼奇怪咋这么快又满了。最终发现是上次 rm 后,占用好几个大G的 contentutil.log 一直被服务A的进程打开了,空间并没有释放。rm 其实是删除该文件名到文件真正保存到磁盘位置的链接,此时该文件句柄还被服务A打开,因此对应的数据并没有被回收,其实可以理解为 GC 里面的引用计数,rm 只是减少了引用计数,并没有真正的进行释放内存,当引用计数为0的时候,OS 内核才会释放空间,供其他进程使用。所以当A进程停止(文件句柄的引用计数会变为0)或者重启后,占用的存储空间才被释放(从某种程度上讲说明该服务一直很稳定,可以连续跑很久不出故障~ 微笑脸)。(tip:如果不知道具体进程或文件名的话:lsof | grep deleted,这样会查找所有被删除的但是文件句柄没有释放的文件和相应的进程,然后再kill掉进程或者重启进程即可)。

其实可以简单用修改文件内容的方式(例如echo "">contentutil.log)在不用重启进程的情况下释放空间。

du vs ls

前两天该问题又出现了,该服务A的日志文件(contentutil.log)占用了约7.6G(请原谅我们没有对该服务的日志做logrotate)。

这一次学聪明了,直接用echo 'hello' > contentutil.log,然后 df 确认磁盘空间确实已经释放,心想着这次可以 Happy 了,突然手贱执行了下 ls 和 du,有了以下结果:

[root@xxx shangtongdai-content-util]# ls -lah contentutil.log
-rw-r--r--. 1 root root 7.6G Nov  7 19:36 contentutil.log
[root@xxx shangtongdai-content-util]# du -h contentutil.log
2.3M    contentutil.log

反正我看到这样的结果是百思不得其解。可以明确的是,这里的 ls 和 du 结果肯定代表不同的含义,具体原因不详,在查阅相关资料和咨询强大的票圈后了解到,这大概与文件空洞和稀疏文件(holes in ‘sparse’ files)相关。

ls 的结果是 apparent sizes,我的理解是文件长度,就类似文件系统中 file 这个数据结构中的定义文件长度的这个字段,du 的结果 disk usage,即真正占用存储空间的大小,且默认度量单位是 block。(apparent sizes 和 disk usage 说法摘自 man du 中的 --apparent-size 部分)

给出一个具体的示例:

// Mac OS 10.11.6 (15G1004)
➜ _drafts git:(source) ✗ echo -n a >1B.log
➜ _drafts git:(source) ✗ ls -las 1B.log
8 -rw-r--r-- 1 tanglei staff 1 11  9 00:06 1B.log
➜ _drafts git:(source) ✗ du 1B.log
8  1B.log
➜ _drafts git:(source) ✗ du -h 1B.log
4.0K 1B.log

上面示例中,文件 1B.log 内容仅仅包含一个字母”a”,文件长度为1个字节,前面的 8 为占用的存储空间 8 个 block,(ls -s 的结果跟 du 的结果等价,都是实际占用磁盘的空间),为什么1个字节的文件需要占用8个 block 呢?可以这样理解, block 为磁盘存储的基本的单位,方便磁盘寻址等(这里说的基本单位应该是磁盘物理结构单位例如一个扇区/柱面等, 对应一个物理单位),而此处的block可以理解为一个逻辑单位,且一个文件除了包括数据外,还需要存储描述此文件的其他信息,因此包含1个字节的文件实际在磁盘中占用的存储空间不止1个字节。默认情况下,Mac中1个逻辑block中是 512 字节,因此 du -h 结果是 8 * 512 = 4096 = 4.0K。

If the environment variable BLOCKSIZE is set, and the -k option is not specified, the block counts will be displayed in units of that size block. If BLOCKSIZE is not set, and the -k option is not specified, the block counts will be displayed in 512-byte blocks. (man du)

因此,通常情况下 ls 的结果应该比 du的结果更小(都指用默认的参数执行,调整参数可使其表达含义相同),然而上面跑服务 A 的机器上 contentutil.log 的对比结果是 7.6G vs. 2.3M, 仍然无法理解了。
沿着 man du 可以看到:

although the apparent size is usually smaller, it may be larger due to holes in (‘sparse’) files, internal fragmentation, indirect blocks, and the like

即因contentutil.log是一个稀疏文件,虽然其文件长度很大,到7.6G了,然而其中包含大量的holes并不占用实际的存储空间。

talk is cheap

下面用一个具体的例子来复现以上遇到的问题。注意以下例子为 Linux version 2.6.32 (Red Hat 4.4.7)中运行结果,且在 Mac 中并不能复现(后文有指出为什么我的Mac不能复现)。

// 从标准输入中读取 count=0 个block, 输出到 sparse-file 中,
// 一个 block 的大小为1k(bs=1k), 输出时先将写指针移动到 seek 位置的地方
[root@localhost ~]# dd of=sparse-file bs=1k seek=5120 count=0
0+0 records in
0+0 records out
0 bytes (0 B) copied, 1.6329e-05 s, 0.0 kB/s
// 所以此时的文件长度为: 5M = 5120*1k(1024) = 5242880
[root@localhost ~]# ls -l sparse-file
-rw-r--r--. 1 root root 5242880 Nov 8 11:32 sparse-file
[root@localhost ~]# ls -ls sparse-file
0 -rw-r--r--. 1 root root 5242880 Nov 8 11:32 sparse-file
// 而 sparse-file 占用的存储空间为 0 个 block
[root@localhost ~]# du sparse-file
0  sparse-file
[root@localhost ~]# du -h sparse-file
0  sparse-file

此时若用 vim 打开该文件,用二进制形式查看 (tip :%!xxd 可以更改当前文件显示为2进制形式),能看到里面的内容全是0。或者直接用od命令查看2进制。

// vim 二进制查看
0000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
....
//od -b sparse-file
0000000   000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
*
24000000

实际上,Sparse 文件是并不占用磁盘存储空间的,那为什么能看到文件里面包含很多0? 因为当在读取稀疏文件的时候,文件系统根据文件的 metadata(就是前面所指描述文件的这个数据结构)自动用0填充[ref Wiki]; Wiki上还说,现代的不少文件系统都支持 Sparse 文件,包括 Unix 及其变种和 NTFS,然而Apple File System(APFS)不支持,因此我在我的 Mac 上用 du 查看占用空间与 ls 的结果一致。传闻指出 Apple 在今年6月的 WWWC 上宣称支持 Sparse 文件。(貌似目前我的系统版本还不支持)

// In Mac
➜ ~ dd of=sparse-file bs=1k seek=5120 count=0
0+0 records in
0+0 records out
0 bytes transferred in 0.000024 secs (0 bytes/sec)
➜ ~ ls -ls sparse-file
10240 -rw-r--r-- 1 tanglei staff 5242880 11  9 09:44 sparse-file
➜ ~ du sparse-file
10240  sparse-file

以上是用 dd 等命令创建稀疏文件,也有同学用 c 代码实现了相同的功能。其实就是写文件的时候,改变下当前文件写指针。前面遇到的问题就应该类似。

#include <stdio.h>
#include <fcntl.h>
#include <string.h>int main() {int fd, result;char wbuf[] = "hello";if ((fd = open("./filetest.log", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR))) {perror("open");return -1;}if ((result = write(fd, wbuf, strlen(wbuf)+1)) < 0) {perror("write");return -1;}if ((result = lseek(fd, 1024*1024*10, SEEK_END)) < 0) {perror("lseek");return -1;}if ((result = write(fd, wbuf, strlen(wbuf)+1)) < 0) {perror("write");return -1;}close(fd);return 0;
}

以上先将”hello”写入filetest.log,然后改变文件指针到1024*1024*10(相当于文件长度这个字段变大了),gcc 编译后运行结果文件详情如下:

[root@localhost ~]# ls -ls filetest.log
8 -rw-------. 1 root root 10485772 Nov  9 17:45 filetest.log
[root@localhost ~]# du  filetest.log
8 filetest.log
[root@localhost ~]# du -h filetest.log
8.0K  filetest.log
[root@localhost ~]# ls -lh filetest.log
-rw-------. 1 root root 11M Nov  9 17:45 filetest.log
[root@localhost ~]# od -c filetest.log
0000000 h   e   l   l   o  \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000020 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
*
50000000 \0 \0 \0 \0 \0 \0 h   e   l   l   o  \0
50000014

解释下结果: 文件长度应该是 “hello” 加上 “\n” 共6个字节*2 = 12,再加上1024*1024*10个字节,即为ls产生的结果10485772个字节约11M,而du的结果为8个block也为8k(这台机器上的block大小与前面的Mac不一样,这里是1024)。

Display values are in units of the first available SIZE from –block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environment variables. Otherwise, units default to 1024 bytes (or 512 if POSIXLY_CORRECT is set. (du --help)

总结

总结一下:出现以上问题说明自己对一些基础掌握得尚不牢固,比如:

  • rm 某文件后, 文件占用的磁盘空间并不是立即释放, 而是其句柄没有被任意一个进程引用时才回收;

  • ls/du 命令结果的具体含义;

  • 稀疏文件。

然而这些知识点都在《UNIX环境高级编程》这本书中有讲 (之前走马观花看过不少,咋对稀疏文件等一点印象都木有!) 

以上内容若有不清楚或不正确的地方,还望大家指出,感谢。


6月3日20:00,CSDN 创始人&董事长、极客帮创投创始合伙人蒋涛携手全球顶级开源基金会主席、董事,聚焦中国开源现状,直面开发者在开源技术、商业上的难题,你绝不可错过的开源巅峰对谈!立即免费围观

推荐阅读

  • 因为一个跨域请求,我差点丢了饭碗

  • 没错,你离分布式搜索只差一个Elasticsearch入门!

  • Python开发之:Django基于Docker实现Mysql数据库读写分离、集群、主从同步详解 | 原力计划

  • 全球Python调查报告:Python 2正在消亡,PyCharm比VS Code更受欢迎

  • 无代码来了,还要程序员吗?

  • 再见,Eclipse | 原力计划

  • 区块链共识算法总结 | 原力计划

真香,朕在看了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/517729.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何优化大规模推荐?下一代算法技术JTM来了

阿里妹导读&#xff1a;搜索&#xff0c;推荐和广告是互联网内容提供商进行价值创造的核心业务&#xff0c;在阿里巴巴的电子商务交易平台上&#xff0c;搜索&#xff0c;推荐和广告业务同样具有举足轻重的意义和价值。现在&#xff0c;阿里推荐技术又双叒优化了&#xff0c;新…

Sentinel 基于Nacos规则持久化-推模式

文章目录一、推模式架构图二、原理简述2.1. 组件版本关系2.2. 控制台推送规则三、Sentinel控制台改造3.1. 下载源码3.2. 修改pom3.3. 重要文件复制3.4. 注册地址修改3.5. 请求实例需改3.6. 菜单新增四、编译 & 启动4.1. 先启动nacos4.2. 编译打包4.3. 创建微服务 &&…

都听我的,会养猪种菜的工程师最帅了!

来了&#xff01;今天&#xff0c;阿里数字农业事业部在黑龙江首次亮相&#xff0c;并且定了一个小目标&#xff1a;到2022年&#xff0c;阿里涉农产品全年网络销售额破4000亿元。 黑龙江省牡丹江市的阿里巴巴响水大米种植基地&#xff0c;又到了收割季 数字农业事业部将建立产…

清华硕士一针见血:这些才是机器学习必备的数学基础

现如今&#xff0c;计算机科学、人工智能、数据科学已成为技术发展的主要推动力。无论是要翻阅这些领域的文章&#xff0c;还是要参与相关任务&#xff0c;你马上就会遇到一些拦路虎&#xff1a;想过滤垃圾邮件&#xff0c;不具备概率论中的贝叶斯思维恐怕不行&#xff1b;想试…

如何查看使用 Cloud Toolkit 部署应用的实时日志

之前&#xff0c;我们介绍了《在 IntelliJ IDEA 中部署应用到服务器》。最新版本 Cloud Toolkit 新增了对远程服务器应用部署时&#xff0c;实时日志的查看功能。功能预览如下&#xff1a; 打开应用部署的配置界面&#xff0c;如上图所示&#xff0c;点击「Advanced」标签页&am…

这 10 个云计算错误,会让你的业务一蹶不振!

作者 | John Edwards译者 | 火火酱&#xff0c;责编 | Carol出品 | CSDN 云计算&#xff08;CSDNcloud&#xff09;封图 | CSDN 付费下载自视觉中国乐观主义者们总爱说&#xff1a;“乌云总是镶着金边的”&#xff0c;但他们没有说的是&#xff0c;在乌云下常有狂风、暴雨、闪电…

MySQL 8.0.26 简易配置安装教程 (windows 64位)

文章目录一、软件下载解压1. 官网下载2.下载完成后解压二、mysql配置2.1. my.ini2.2. 初始化MySQL2.3. 安装MySQL服务2.4. mysql已经安装过了2.5. 启动MySQL的服务三、密码修改3.1. 登录mysql3.2. 修改密码3.3. 退出mysql四、客户端连接mysql4.1. Navicat4.2. 登录mysql4.3. 操…

类与字节码技术

类文件结构 1.1 魔数 0-3字节&#xff0c;表示它是否是【class】类型的文件 ​ |java| 0000000 ca fe ba be 00 00 00 34 00 23 0a 00 06 00 15 09 1.2 版本 4-7字节&#xff0c;表示类的版本00 34 &#xff08;52&#xff09; 表示是Java8 0000000 ca fe ba be 00 00 00…

支付宝 App 是如何建设移动 DevOps 的?

本文系InfoQ对蚂蚁金服技术专家洪锋的采访&#xff0c;洪锋老师即将在 QCon 上海站 2019 分享《移动研发 DevOps 在支付宝 App 内的落地实践》&#xff0c;欢迎关注。 微软 MSDN 上的一篇文章有这样一段话&#xff1a;“移动应用的理想环境需要满足两个条件&#xff0c;一是可以…

淘宝端智能演进和思考

今天分享内容包括三部分&#xff0c;第一是端智能整体趋势和淘宝应用现状&#xff0c;第二是淘宝在应用端智能过程中面临的问题和挑战&#xff0c;以及我们的应对和解决思路&#xff0c;我们构建了端到端的完整技术体系&#xff0c;第三是开源推理引擎 MNN 的最新情况。 01、端…

从零开始入门 K8s | 可观测性:你的应用健康吗?

一、需求来源 首先来看一下&#xff0c;整个需求的来源&#xff1a;当把应用迁移到 Kubernetes 之后&#xff0c;要如何去保障应用的健康与稳定呢&#xff1f;其实很简单&#xff0c;可以从两个方面来进行增强&#xff1a; 首先是提高应用的可观测性&#xff1b;第二是提高应…

技术差的程序员,90%都输在这点上!骨灰级开发:其实都是在瞎努力!

01从未得到过重视的问题“一流程序员学数学&#xff0c;二流程序员学算法&#xff0c;低端看高端就是黑魔法”。可能有人会以为这是段子&#xff0c;而有过开发经验的都知道&#xff0c;这就是程序员的真实写照&#xff01;而数学不好的程序员&#xff0c;我想你开发过程中&…

layui 单选项 点击显示与隐藏 很实用

html <div class"layui-form-item"><label class"layui-form-label">类型</label><div class"layui-input-block"><input type"radio" name"type" lay-filter"type" value"0&quo…

2. 字节码指令

2. 字节码指令 2.1 入门 public cn.itcast.jvm.t5.HelloWorld();构造方法的字节码指令 ​ 2a b7 00 01 b1 2a> aload_0加载slot 0的局部变量&#xff0c;即this&#xff0c;做为下面的invokespecial 构造方法调用的参数b7 >invokespecial预备调用构造方法&#xff0c…

它是真实的“盗梦空间”?在这里,一切都可能是数据

阿里妹导读&#xff1a;位于杭州阿里巴巴西溪园区旁边的大型商场“亲橙里”2018年正式开业。和传统的线下综合型商场不同的是&#xff0c;亲橙里从规划之初就定位为数字化商场&#xff0c;通过植入自研的IBOS平台完成建筑内的所有子系统的接入&#xff0c;而让建筑和建筑内的设…

BDS-HA:构建高可用、低延迟的HBase服务

HBase可以支持百TB数据规模、数百万QPS压力下的毫秒响应&#xff0c;适用于大数据背景下的风控和推荐等在线场景。阿里云HBase服务了多家金融、广告、媒体类业务中的风控和推荐&#xff0c;持续的在高可用、低延迟、低成本方向上进行优化。目前单集群承诺可用性99.9%&#xff0…

layui 表单动态添加、删除input框

html部分 <div class"layui-form-item" ><label class"layui-form-label">路线</label><div class"layui-input-block" id"last"><div class"layui-input-inline">{empty name"$ways&q…

MySQL 可重复读,差点就让我背上了一个 P0 事故!

来源 |程序通事责编 | Carol封图 | CSDN 付费下载自视觉中国P0 事故&#xff1a;余额多扣&#xff01;这是一个真实的生产事件&#xff0c;事件起因如下&#xff1a;现有一个交易系统&#xff0c;每次产生交易都会更新相应账户的余额&#xff0c;出账扣减余额&#xff0c;入账增…

AliOS Things 3.0应用笔记:摄像头配网 + 钉钉群通知 + 天气显示

给AliOS Things一颗STAR 目录 运行流程效果展示 操作流程 环境配置源码结构配置烧录运行 源码讲解 QR扫码部分GUI部分https client部分 运行流程 本示例有如下3个功能&#xff1a; 摄像头配网。推送消息到钉钉群。显示当天天气。操作流程 环境配置 AliOS Things环境安装&a…

与阿里合伙人合影,两年净赚一百万,这个草根姑娘有什么魔力?

大学肄业&#xff0c;网店关闭&#xff0c;公司转手&#xff0c;人生的下一步要怎么走&#xff1f;张昕总沉浸在自己的世界里发呆。 直到两年前&#xff0c;张昕随手往几个群里转发了“购买阿里云服务器”的折扣幸运券&#xff0c;半年后&#xff0c;因订单数量排进前十&#…