磁盘空间没满却无法写入:inode、配额与保留块检查
来源:17golang原创
时间:2026-10-07 12:21:19 326浏览 收藏
Linux 报 No space left on device,并不只表示“磁盘字节用完”。创建或扩展文件至少会受到四类限制:文件系统的数据块、可分配 inode、当前用户/组/项目的配额,以及 ext2/3/4 留给特权进程的保留块。只看一眼 df -h 的容量百分比,很容易删错目录或误改文件系统参数。
我处理这类问题时,先固定报错路径和执行身份,再记录四组基线指标。目标不是立刻“释放一点空间”,而是找出哪一个计数先到边界。ENOSPC 表示设备没有可用空间,EDQUOT 表示磁盘配额耗尽;不少应用会把底层错误统一包装成相似文案,所以最终仍要回到文件系统指标。
GNU df 官方文档:https://www.gnu.org/software/coreutils/manual/html_node/df-invocation.html
Linux 内核 ext4 文档:https://www.kernel.org/doc/html/latest/filesystems/ext4/
- 先用
findmnt -T确认报错目录究竟落在哪个挂载点和文件系统。 df -h看数据块,df -i看 inode;两者是独立资源。- 两组都有余量时,检查当前用户、组或项目是否碰到配额 hard limit。
- 只有文件系统是 ext2/3/4 时,才检查特权进程保留块;不要把 XFS、Btrfs 或网络文件系统套进 ext 的处理方式。
先建立基线:确认路径、挂载点和四组指标
一次让我印象很深的故障发生在日志目录:根分区看起来还有空间,应用却无法创建新的轮转文件。最初大家围着最大的日志删文件,后来才发现应用目录是单独挂载,且小文件把 inode 用完了。这个经历之后,我不再从设备名猜挂载点,而是始终让命令围绕真实报错路径执行。
# 把这里改成真正报错的目录,所有检查都围绕同一路径进行。 target_path="/srv/app/data" # 确认该路径对应的设备、文件系统类型、挂载点和挂载选项。 findmnt -T "$target_path" -o SOURCE,FSTYPE,TARGET,OPTIONS # 检查数据块总量、已用量、普通进程可用量和使用率。 df -hT -- "$target_path" # 检查 inode 总数、已用数、可用数和 IUse%。 df -i -- "$target_path"
df 接收路径时,会报告包含该路径的文件系统;-i 则把块使用信息换成 inode 使用信息。GNU 文档把 inode 定义为保存文件所有者、权限、时间戳和磁盘位置等信息的索引节点。对 ext4 来说,inode 表按块组预先组织,因此“还有很多数据块”和“还能不能创建新文件”是两个问题。
| 基线指标 | 危险证据 | 优先假设 |
|---|---|---|
df -h 的 Avail | 普通进程可用量为 0 | 数据块耗尽,或只剩特权进程保留块 |
df -i 的 IFree / IUse% | IFree 为 0 或 IUse% 为 100% | inode 耗尽,常见于海量小文件 |
quota 的 used / hard | 块或文件数达到 hard limit | 用户、组或项目配额阻止继续写入 |
| 文件系统类型 | ext2、ext3 或 ext4 | 继续核对保留块;其他类型走各自工具 |

假设一:inode 用完,字节容量仍然充足
inode 耗尽最符合“空间没满却创建不了新文件”的直觉冲突。一个很大的文件通常只占一个 inode,而百万级缓存碎片、会话文件、邮件队列或未清理的空文件,会快速消耗 inode,却未必占用多少数据块。
# 继续检查同一目标路径,避免把其他分区的 inode 指标当成证据。 target_path="/srv/app/data" df -i -- "$target_path" # 只在已确认的挂载点内按目录汇总文件数量,-xdev 避免跨入其他文件系统。 find "$target_path" -xdev -type f -printf '%h\n' \ | sort \ | uniq -c \ | sort -nr \ | head -n 20
第二段命令可能在文件极多时本身也比较重,应先缩小到业务已知目录,并避开高峰。证据成立时,正确动作通常是按业务保留期清理、归档或合并小文件,调整缓存和轮转策略;不是去删除某个大文件。inode 数量通常在文件系统创建时确定,后续不能把剩余字节简单“转换”为 inode。
复测也必须看两项:删除或归档后,IFree 应增加;应用使用原身份在原目录创建文件应恢复。只看到 df -h 的 Used 降低,不足以证明 inode 问题已经解决。
假设二:当前身份达到配额,文件系统全局仍有余量
配额是另一套独立计数。Linux 配额系统可以对用户、组和项目限制文件系统中的空间与 inode 使用量。hard limit 不能超越;soft limit 可以暂时超过,但过了宽限期会按硬限制处理。于是管理员查看全局 df 时还有余量,应用账号仍可能收到配额错误。
# 以当前登录身份查看用户配额,-s 使用易读单位。 quota -s # 查看当前用户所属组的组配额;不同发行版可能需要安装 quota 工具包。 quota -g -s # 管理员汇总本机已启用文件系统的用户与组配额,命令仅做报告。 sudo repquota -a
检查时要同时看空间块和文件数限制。有些账号没有碰到字节 hard limit,却已经达到 inode hard limit;有些容器或工作目录使用项目配额,普通 quota -s 看不到项目维度,需要按文件系统类型使用管理工具核对项目 ID。
如果配额正是组织的隔离策略,不要通过换成 root 写入来“绕过去”。合理修复是清理该身份拥有的过期数据,或由管理员根据容量预算调整 hard limit。调整后用同一个应用账号、同一个目录复测,避免管理员身份成功而业务进程仍失败。
假设三:ext 保留块让普通进程先看到 Avail 为零
ext2、ext3 和 ext4 可以保留一部分文件系统块,只允许特权进程分配。tune2fs 手册说明,这样做一方面降低文件系统严重填满时的碎片风险,另一方面让 syslogd 等系统守护进程在普通进程被禁止写入后仍能继续工作;默认保留比例通常是 5%。
这个机制只应在 findmnt 已确认文件系统为 ext2/3/4 后检查。下面命令只读取超级块,不修改参数:
# 从真实报错路径解析底层设备和文件系统类型。
target_path="/srv/app/data"
filesystem_type="$(findmnt -n -o FSTYPE -T "$target_path")"
source_device="$(findmnt -n -o SOURCE -T "$target_path")"
# 只有 ext2/3/4 才使用 tune2fs 读取保留块;其他类型必须改用对应工具。
case "$filesystem_type" in
ext2|ext3|ext4)
sudo tune2fs -l "$source_device" \
| grep -E 'Block count|Free blocks|Reserved block count|Reserved block percentage'
;;
*)
printf '文件系统 %s 不适用 tune2fs 保留块检查\n' "$filesystem_type"
;;
esac
如果 df -h 显示普通进程的 Avail 已接近零,而超级块仍有明显的 Reserved block count,就能解释为什么 root 还能写、业务账号却失败。但这不是“隐藏的免费空间”。直接把保留比例调到 0 会削弱系统在满盘时保留日志、远程登录和清理能力,尤其不适合根文件系统。
对于超大、纯数据用途且有独立监控和应急预案的 ext 文件系统,可以在容量评审后评估较低比例;真正的长期方案仍是扩容、限流和清理策略。本文只检查,不给出一条可盲目复制的修改命令。

按证据改动,而不是按错误文案猜原因
| 证据组合 | 结论 | 优先处置 | 不建议 |
|---|---|---|---|
| Avail 为 0,inode 有余量 | 数据块或保留块边界 | 先清理/扩容,再按文件系统类型检查保留策略 | 只删大量空文件 |
| IFree 为 0,块有余量 | inode 耗尽 | 归档小文件,修正缓存与轮转 | 只删除一个大文件 |
| 块和 inode 都有余量,quota 达 hard | 身份配额限制 | 清理该身份数据或审批调整配额 | 改用 root 绕过 |
| ext 文件系统、普通 Avail 为 0、仍有保留块 | 只剩特权保留容量 | 恢复安全余量,评估专用数据盘比例 | 在根分区盲目设为 0 |
如果四组指标都没有触边,就要扩大排查范围:挂载点是否变成只读、应用是否写到另一个 namespace、删除但仍被进程打开的文件是否占用块、底层存储或网络文件系统是否延迟分配失败。它们同样可能造成写入失败,但不能用 inode、配额或保留块的结论硬解释。
复测方法:同一路径、同一身份、同一类型操作
修复后,我会保留变更前后的四项数值,而不是只看应用重启后“暂时不报错”。复测应满足:
findmnt -T仍指向预期挂载点,没有把测试写到别的文件系统。df -h的 Avail 留出运维安全余量,不是刚从 0 变成极小值。df -i的 IFree 明显恢复,并且增长速度受清理或轮转策略约束。- 应用身份的空间和文件数配额都低于 hard limit,必要时也核对项目配额。
- 使用业务进程的同一用户,在原目录完成真实的创建、追加和删除,而不是只让 root 执行
touch。
指标驱动的价值在这里很直接:inode 问题修复后,IFree 会变化;配额问题修复后,used 与 hard 之间会重新出现余量;保留块问题则会体现为普通进程可用量与特权可用范围的差异。每个改动都应有对应数字,而不是依赖“删了一些东西”的感觉。
常见问题
df -h 没到 100%,为什么仍然写不进去?
先看 Avail 而不是只看 Use%。还要核对 inode 和配额。ext 文件系统只剩保留块时,普通进程可能已经没有可分配块,而特权进程仍保有应急空间。
df -i 的 IUse% 为 100% 应该删大文件吗?
通常优先找海量小文件。大文件和小文件都需要 inode,但一个大文件通常只占一个 inode;删除单个大文件会释放数据块,却未必解决 inode 耗尽。
root 能写、应用账号不能写就一定是保留块吗?
不一定。用户、组或项目配额以及目录权限也会造成身份差异。先看 errno、quota 报告和文件系统类型,再判断是否是 ext 保留块。
可以直接把 ext4 保留块比例改成 0 吗?
不建议把它当成通用修复。根文件系统尤其需要保留应急写入能力。专用大数据盘是否降低比例,应结合容量、碎片风险、监控和故障恢复方案单独评审。
“磁盘空间没满却无法写入”不是一个单指标问题。数据块回答还能写多少字节,inode 回答还能创建多少文件对象,配额回答当前身份还能使用多少资源,保留块回答普通进程与特权进程的可用边界。把这四类证据放在同一个目标路径上,排障才会从猜测变成可复查的判断。
-
156 收藏
-
462 收藏
-
252 收藏
-
422 收藏
-
383 收藏
-
189 收藏
-
373 收藏
-
文章 · linux | 7小时前 | linux运维 · 故障排查 · 服务管理 · systemctl journalctl RestartSec StartLimitBurst Restart systemd 服务432 收藏
-
150 收藏
-
116 收藏
-
258 收藏
-
268 收藏
-
294 收藏
-
483 收藏
-
455 收藏
-
181 收藏
-
439 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习