磁盘与文件系统排查
文件系统通过目录项、inode 和数据块组织文件。本文负责磁盘容量、文件删除与缓存写回。
1. 面试核心
先记住这几条,再读正文- 文件名与 inode。 目录项关联文件名与 inode,inode 保存文件元数据。卡 · inode 与文件系统结构
- 空间与 inode 耗尽。
df -h查看块空间,df -i查看 inode 使用量。卡 · 磁盘容量排查 - 空间统计口径。
df统计文件系统空间,du遍历可见文件并累计占用。卡 · 空间占用与 df、du 差异 - 删除与打开引用。 已删除文件仍被打开时,其存储空间继续保留。卡 · 空间占用与 df、du 差异
- 持久化保证。
fsync同步文件数据与必要元数据,目录项需另行同步。卡 · 稀疏文件与持久化
2. inode 与文件系统结构
| 对象 | 保存内容 |
|---|---|
| 目录项 | 文件名与 inode 号的对应关系 |
| inode | 类型、权限、属主、大小、时间和数据位置 |
| 数据块 | 文件内容 |
ext4 还包含超级块、位图和 inode 表。路径查找逐级解析目录项,找到目标 inode。目录及 inode 缓存能减少实际磁盘读取。
硬链接是指向同一 inode 的不同名称。删除一个名称会减少链接数。剩余名称仍可访问该文件。
ext4 在创建文件系统时配置 inode 容量。扩展文件系统可增加块组和 inode。大量小文件仍可先耗尽 inode。其他文件系统的 inode 分配方式应分别确认。
ls -i 查看 inode 号,stat file 查看元数据。同一文件系统内的普通 rename 主要改变目录项。跨文件系统移动需要复制再删除。
3. 磁盘容量排查
- 用
df -h与df -i确认挂载点和耗尽资源。 - 用 du 逐层定位目录,并注意访问权限。
- 用 find 查找大文件或大量小文件的来源。
- 核对打开文件、业务用途与保留策略后处理。
- 通过轮转、配额和增长告警控制后续写入。
du -xh --max-depth=1 /data | sort -rh | head
find /data -xdev -type f -size +1G -exec ls -lh {} \;
du --inodes -x --max-depth=1 /data | sort -nr | head
这里使用 GNU du。前两条定位空间大户,第三条比较 inode 数量。-x 和 -xdev 将范围限制在同一文件系统。
正在写入的日志优先通过应用轮转并重新打开。旧文件关闭后,再按策略清理。截断会丢弃已有内容,还会保留原文件偏移。非追加写入沿用原偏移。若该偏移超过新文件长度,后续写入会产生空洞。因此,截断只适合已确认写入语义的场景。
4. 空间占用与 df、du 差异
| 现象 | 核对方向 |
|---|---|
| 删除后 df 用量不降 | lsof +L1 查已删除但仍打开的文件 |
| df 高、du 低 | 打开文件、挂载遮挡、元数据和访问权限 |
| 文件可见大小很大、du 很小 | 稀疏文件 |
| 空间未满却写入失败 | inode、配额、预留块、只读挂载与 I/O 错误 |
unlink 删除目录项。最后一个硬链接消失后,打开引用仍会延长文件生命周期。内存映射也可持有文件引用。释放最后引用后,文件系统才可回收空间。
lsof +L1 用于寻找链接数小于 1 的打开文件。找到持有者后,可通知应用重新打开日志。重启也能关闭引用,但需评估业务影响。
挂载会遮住目录中原有内容。维护时可用额外的非递归绑定视图检查底层目录。直接卸载业务挂载点会中断访问,应按维护方案操作。
5. buffer 与 cache
页缓存保存文件内容。缓冲写入先修改缓存页,再由写回流程落盘。块设备缓存则用于块设备访问。
procps 的 free 将多类缓存汇总为 buff/cache。它包含 buffers、页缓存与可回收 slab。该值并非全部都能立即回收。
available 估算在不发生交换时还能提供多少内存。脏页需写回,部分 slab 也无法即时释放。因此,还需结合交换速率和内存压力判断。
清理缓存会让后续读取重新访问存储。性能排查应先确认压力来源。手工 drop_caches 只适合明确的测试需求。
6. 稀疏文件与持久化
稀疏文件的逻辑大小可大于已分配空间。未分配区间读取为零。ls -l 显示逻辑大小,du 默认统计已分配块。du --apparent-size 可比较逻辑大小。
write() 成功说明数据已被系统接受。缓冲 I/O 下,数据还会等待写回。fsync(fd) 将文件数据与元数据同步到存储设备。调用还需检查返回值和设备错误。
新建文件或 rename 后,目录项也需要持久化。应用应对相关目录描述符执行 fsync。文件内容同步与目录项同步分别承担不同任务。fdatasync 只同步数据及读取数据所必需的元数据。
7 · 面试题卡片
本页题目与参考回答
7.1 什么是 inode?文件系统由哪些部分组成?
考察重点
- 目录项、inode、数据块的分工;文件名不在 inode 中。
- inode 数量有限,以及由此引出的 inode 耗尽和硬链接。
相关内容:inode 与文件系统结构。
参考回答
inode 保存文件类型、权限、属主和数据位置等元数据。
文件名由目录项保存。路径查找通过目录项找到 inode,再访问数据。
硬链接是同一 inode 的不同名称。ext4 的 inode 容量受格式化和后续扩容影响。大量小文件会先耗尽 inode。排查时用 df -i 区分 inode 与块空间。
7.2 磁盘使用率很高甚至打满了,你怎样排查和处理?
考察重点
- 区分空间满和 inode 满。
- 用
du、find逐层定位;安全地清理正在写入的文件;事后的预防。
相关内容:磁盘容量排查。
参考回答
先区分块空间耗尽、inode 耗尽和其他写入错误。
df -h 与 df -i 确认挂载点。du -x 逐层查目录,find 查大文件。GNU du 的 --inodes 可比较 inode 使用量。
清理前确认业务用途、打开引用与保留策略。日志优先轮转并让应用重新打开。截断需确认内容可丢弃及追加写入语义。之后补充轮转、配额、容量与增长告警。
7.3 删除了大文件但空间没有释放,或者 du 找不到大文件但 df 显示快满了,可能是什么原因?
考察重点
- 删除操作只减少链接计数,进程打开的文件不会释放。
- df 与 du 的统计方式不同;挂载点遮挡和隐藏文件。
相关内容:空间占用与 df、du 差异、inode 与文件系统结构。
参考回答
已删除但仍被打开的文件,是常见原因。
unlink 移除目录项,打开引用仍保留文件。du 遍历不到该名称,df 仍统计已分配空间。
先用 lsof +L1 找持有进程。让应用关闭旧日志并重新打开,才能释放引用。还要核对挂载遮挡、权限和文件系统元数据。稀疏文件则会让逻辑大小大于实际占用。
7.4 buffer 和 cache 有什么区别?
考察重点
- 页缓存缓存文件内容,buffer 缓存块设备数据。
- 理解缓存回收条件与
available的含义。
相关内容:buffer 与 cache。
参考回答
页缓存保存文件内容,buffer 对应块设备缓存。
free 的 buff/cache 还包含可回收 slab。脏页需要写回,缓存也有暂时无法回收的部分。
判断内存压力应看 available、交换速率和压力指标。available 估算无交换时可供新应用使用的内存。单看 free 很低,无法判断内存已经不足。
7.5 为什么 ls 与 du 的大小不同?write 成功后文件就能抗断电吗?
考察重点:稀疏文件、缓存写入与目录同步。
相关内容:稀疏文件与持久化。
参考回答
ls 显示逻辑大小,du 默认统计已分配块。
稀疏文件的空洞会造成两者差异。write 成功后,缓冲数据仍可处于页缓存。持久化需执行 fsync 并检查返回值。新建或重命名还需同步相关目录。