服务器入坑指北:预留空间与紧急腾挪的取舍

举报
Tulpartner 发表于 2026/11/06 08:55:15 2026/11/06
【摘要】 目录里明明还有空间,服务却报"设备上没有空间";df 显示的总量,怎么算都对不上"已用加可用";真到了要紧的时候,只能靠删日志腾地方,删完又不敢确认到底腾出来多少。 顺序是:先把"预留"这笔账算出来 → 再判断该不该动它 → 腾挪时先干跑、后动手。

目录里明明还有空间,服务却报"设备上没有空间";df 显示的总量,怎么算都对不上"已用加可用";真到了要紧的时候,只能靠删日志腾地方,删完又不敢确认到底腾出来多少。
顺序是:先把"预留"这笔账算出来 → 再判断该不该动它 → 腾挪时先干跑、后动手。
这篇给三段可直接粘贴的内容:第一段只读(现读水位与算账)、第二段只读(腾挪三步,先干跑)、第三段含写操作(改预留比例并读回,标回滚点)。取值用占位符,命令名、字段名与配置键照写。

先算清"预留"这笔账

同一个挂载点上,「已用 + 可用」与「总容量」通常不相等——差额就是被预留吃掉的那块。这块预留不是损耗,而是留给特权进程的余量:普通用户能用的量来自另一个字段。
这也是"目录里还有空间、服务却说写不进去"这类现象的成因之一:报错本体是 ENOSPC(设备上没有空间),而"没有空间"要按普通用户可用量去算,不是按总空闲算。

现读与算账块

df -h <挂载点>                                   # 现读水位:已用 + 可用 ≠ 总容量,差额就是预留
df --output=source,size,used,avail,pcent <挂载点>  # 把四列摆在一起,直接做减法
stat -f -c '%b %f %a %S' <路径>                    # 块总数 / 全部空闲 / 非特权可用 / 块大小
tune2fs -l <设备>                                 # 读预留块数与块大小(字段名以现读为准)

判据(两个字段名要分清):

  • **f_bfree(全部空闲块)**与 f_bavail(非特权可用块)是两个不同的量——两者之差就是普通用户吃不到的那部分预留;
  • f_frsize 是换算基数:块数 × 块大小 = 容量;
  • df 与 stat 的数字都来自同一个系统调用(statvfs),所以它们本来就应当互相对得上——对不上说明你看的不是同一个挂载点。

算一遍:三处例证

例证一:四列做减法。 设总容量 100 GiB、已用 40 GiB、可用 55 GiB:
100 - 40 - 55 = 5(GiB)——这 5 GiB 就是预留;普通用户看到的是 55 GiB,而不是 60 GiB。
例证二:容量乘比例。 预留比例的字段名是 reserved-blocks-percentage,默认取 5%:
100 GiB × 5% = 5 GiB——与例证一算出来的差额一致。两条路必须得出同一个数,否则就是你读错了列。
例证三:块数与块大小的换算。 设块大小 4096 字节:

  • 预留块数 = 5368709120 字节 ÷ 4096 = 1310720 块(其中 5368709120 字节就是 5 GiB);
  • 反过来验证:1310720 × 4096 = 5368709120(字节)≈ 5 GiB;
  • 于是 f_bfree - f_bavail = 1310720 块——这也就是"普通用户吃不到的那部分预留量"的块数形态。
    判据:这三个数是同一条链上的三个说法(颜色、比例、块数),能互相换算,所以任何一处对不上都能反查出读错的那一列。

腾挪三步:先干跑,后动手

在清理之前先干跑一遍——systemd-tmpfiles --dry-run --clean 会只输出它打算删什么、不真的删。这条要写在动手之前。

du -x -d <层数> <路径> | sort -h                 # 第一步:按目录从大到小找大户
find <路径> -xdev -type f -size +<大小>           # 第二步:按大小捞出候选对象
lsof +L1                                         # 第三步:已删除但仍被进程占用的文件
systemd-tmpfiles --dry-run --clean               # 干跑:先看清要删什么,再真清

判据:

  • du -x -d <层数> <路径> | sort -h 里的 -x 不跨文件系统——别把别的挂载点的占用算到这个盘上;
  • lsof +L1 的那一类特别值得注意:文件已经删了,但进程还拿着它——占用在 df 里看得见、在目录里找不到,这就是"删了却没腾出空间"的常见成因;
  • 干跑的输出与你的预期逐条对上再执行;清理依据是 Age 字段(它与现读时间之差决定该不该清)。

取舍:动预留,还是腾空间

  • 动预留(调低预留比例,如 tune2fs -m <百分比> <设备>):立刻多出一块可用量;代价是特权进程的余量变小——真到系统需要那点余量时,你也没有了;
  • 腾空间(清理、搬走大户):不动预留的语义;代价是要花时间、且可能删到有用的东西,所以要先干跑。
    判据:先腾空间,再考虑动预留;动预留属高风险写操作,需回滚点——先记下当前比例,改完用 tune2fs -l <设备> 读回。
    另外一个方向是建文件系统时就定下来:mkfs.ext4 -m <百分比> <设备> 决定初始比例,事后才发现预留不够(或太多)都属于补救。

改与读回块

tune2fs -l <设备>                                # 改前:记录当前的预留比例与块大小
tune2fs -m <百分比> <设备>                        # 调预留比例(高风险写操作,需回滚点)
df --output=source,size,used,avail,pcent <挂载点>  # 读回:可用量变化与算出来的差额是否一致
stat -f -c '%b %f %a %S' <路径>                    # 读回:f_bfree 与 f_bavail 的差有没有按预期变化

读回是独立的一步,不许省:改完要确认可用量的变化量与"容量 × 比例变化"算出来的数一致——不一致说明你改的不是那个挂载点,或者中间还有别的层。

现象到动作的判定表

现象 结论 动作
目录里还有空间却报 ENOSPC 该看的是非特权可用量 用 df --output=… 摆开四列,算 f_bfree - f_bavail
已用 + 可用与总量对不上 差额是预留 用 tune2fs -l <设备> 读出预留块数与总块数,再按 预留块数 / 总块数 算出比例
删了文件却没腾出空间 文件已删除但仍被占用 lsof +L1 找持有者,重启或让它释放
腾挪不知道从哪下手 没有按量排序 du -x -d <层数> <路径> | sort -h,再 find … -size +<大小>
清理怕删错 没有干跑 先 systemd-tmpfiles --dry-run --clean,输出与预期逐条对上再执行

改完怎么验证:每项一条判据

  • 可用量的变化与算式一致(容量 × 比例变化);
  • 预留块数与"全部空闲减非特权可用"对得上;
  • 大户已按量排序处理(不是凭感觉删);
  • 被删除但仍被占用的文件已确认释放;
  • 有回滚形态与原值记录。

这篇不解决什么

  • 讲配额满了不是磁盘满的那篇是按主体计量的限额;本篇是文件系统自身的预留——一个按"谁"计,一个按"盘"计。
  • 讲磁盘还有空间却写不进去的那篇是空间与 inode 耗尽的分流;本篇接住它的"预留"这一支,讲怎么算、怎么动。
  • 讲容器层占用与清理的那篇是容器那一侧的占用;本篇是文件系统层的余量。

踩坑清单

  • 拿总空闲当可用量:普通用户看到的是非特权可用那一项。
  • 只看 -h 的人读结果,不做减法:差额就是预留,不算就永远对不上。
  • 把 f_bfree 与 f_bavail 当同一个量:两者之差就是预留块。
  • 忘记块数要乘块大小:f_frsize 是换算基数。
  • 删了文件却没腾出空间:lsof +L1 那一类还占着。
  • 直接动预留比例不留回滚点:改完说不清原来是多少。
  • 用 du 统计时忘了 -x:把别的挂载点算进来。
  • 清理不干跑:删掉之后才发现删错了。
  • 忽略 Age 字段:清理依据对不上,误删或漏删。
  • 在还没确认是不是预留问题时就降比例:先算账,再动手。
  • 只改一次不读回:不知道改的是不是那个挂载点。
  • 把预留降到零当"省空间":系统的余量被一起吃掉了。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。