ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux磁盘配额实战:ext4与XFS下的软限制、硬限制配置与管理

Linux磁盘配额实战:ext4与XFS下的软限制、硬限制配置与管理

前阵子我拿一台离线测试服务器练手,折腾到一半系统突然开始疯狂报错,所有写磁盘的操作全部失败。登录一看,/home 分区可用空间已经是 0%。排查完才发现,这台机器没有做任何磁盘配额管理,所以一个失控进程就能把整个分区写爆。在那之后,我把配额(quota)机制从“听过但没细研究”变成了生产环境的必备项。这篇文章我想把手上的完整思路梳理清楚:磁盘配额到底解决什么问题、软限制和硬限制怎么理解、ext4 和 XFS 两套操作方式有什么区别、多人环境下怎么批量配置和监控,以及我在实际使用中踩过的那些坑。如果你维护的是多用户服务器、公共文件存储、CI 构建机或者各种共享开发环境,这篇文章应该能直接拿去落地。

1. 一次写满磁盘的复盘:配额到底是解决什么问题的

1.1 事故现象:所有写入瞬间失败

那台服务器原本跑得挺正常,直到某天我在上面做文件同步实验,突然发现 rsync 报 “No space left on device”。一开始我以为是磁盘真的满了,df 一看,/home 确实 100% 占满。可奇怪的是,系统盘 / 还有不少空间。问题出在 /home 这个独立分区上。

这时候最麻烦的事情出现了:因为 /home 被写满,所有需要生成临时文件的程序都开始报错,连我登录后想创建个排查用的脚本都写不进去。整个分区变成一个“只读”状态——不是权限只读,而是物理上没有任何空闲块。找到元凶之后我更是哭笑不得,是一个测试账号下跑崩的模拟任务,日志文件没做轮转,一个进程写了 40 多 GB 的 log,直接把分区灌满了。

1.2 排查链路:从“磁盘满”到“谁写满了磁盘”

当时排查的思路其实不难,但每一步都耗时:

  • 先用df -h确认是哪个挂载点满了;
  • 再用du -sh /home/*逐个目录统计,找到占用最大的目录;
  • 然后进目录里用du -sh * | sort -rh定位到大文件;
  • 最后找到对应进程,kill 掉,清理文件,系统才恢复正常。

这个过程看起来简单,但如果生产环境里有几百个用户、几十个服务,靠 du 一个个翻是很痛苦的。更重要的是,清理完之后问题还会复发——只要没有限制机制,任何用户随时都可能把磁盘再次写满。那次事故之后我做的第一件事,就是把磁盘配额打开。

1.3 为什么不能靠“手动清理”过日子

有人说,那我可以写个巡检脚本,每天扫描超过阈值的目录然后报警。这种思路不是不行,但它是事后补救:脚本扫描时磁盘可能已经满了,服务已经挂了。配额机制的优势在于它是 Linux 内核层的限制,用户写入时系统直接拦截,不需要额外的守护进程,也不会出现“先破坏再发现”的时间差。

配额能管两件事:

  • 限制用户可以占用的磁盘空间(比如每个人最多 10GB);
  • 限制用户可以创建的文件数量(比如每个人最多 5 万个文件)。

它适合的场景非常明确:多用户共享一台机器的盘、FTP/文件服务、邮件服务器、CI 构建节点、挂载了公共存储的测试环境。而对于单用户个人电脑,配额的意义不大,反而添麻烦。另外要明确一个边界:配额管不了 CPU、内存这些资源,那是 cgroup 和 systemd 管理的领域。配额只管“这块盘上谁能写多少”。

2. 配额机制拆解:软限制、硬限制、宽限期以及两层记账维度

2.1 用户配额与组配额:限制对象不同

先理清两个基本概念:用户配额和组配额。

用户配额是对单个 Linux 用户生效的限制,最常见的用法。比如给testuser配置 5GB 上限,那么无论他写什么都受这个限制。组配额则是对一个用户组整体的限制,适合团队协作场景——比如一个项目组的几个人共享 20GB 空间,不管组里谁写,总量不能超过。两者可以同时启用,也可以只启用其中一个。

我在实际使用中的习惯是:优先做用户配额,因为用户配额语义最简单,用户之间互不影响。组配额适合那种“一个组共用目录”的场景,但如果组内成员很多,又需要细分个人空间,靠组配额就不够灵活了,还得叠加用户配额。

2.2 软限制、硬限制与宽限期:阶梯式管控

配额不是简单设一个“最多用多少”就完了,内核把它拆成了三个概念:

  • 软限制(soft limit):用户可以超过这个值,但不能长期超过;
  • 硬限制(hard limit):绝对上限,超过就不让写;
  • 宽限期(grace period):用户超过软限制后,内核开始倒计时,默认是 7 天。

整个流程可以这样理解:使用量小于软限制时,一切正常;超过软限制但没到硬限制时,系统允许继续写,但宽限期开始计时;如果宽限期到了还没把使用量降回软限制以下,内核就开始拒绝新增写入;如果超过了硬限制,那不用等宽限期,直接拒绝。

这个设计其实很像生活中的“缓冲期”:给用户一个临时超限的处理窗口,避免硬性一刀切导致业务中断。我个人的建议是,软限制设成正常使用量的 1.2 倍左右,硬限制再留 20%-30% 的余量,给用户充分的周转空间。

2.3 块配额与 inode 配额:空间和数量的双重约束

配额还有两个维度:块配额和 inode 配额。

  • 块配额限制的是磁盘空间大小,内核按数据块记账,配额工具里看到的blocks字段,单位通常是 1KB;
  • inode 配额限制的是文件数量,每一个文件或目录都会占用一个 inode,所以它管的是“你能创建多少文件”。

为什么不只管空间?因为很多服务被“写满”不一定是因为空间大,而是文件数量爆炸。典型例子是邮件服务器:如果有用户无限创建小文件,每个文件哪怕只有 1KB,几百万个文件也能把 inode 表耗尽,导致整个分区无法再创建任何新文件,即使空间还有几十 GB。所以我在给文件服务类服务器做配额时,两个维度都会设置。

2.4 底层记账:配额数据库与文件系统元数据

传统 ext4 系列的记账方式是:内核在写入时检查当前用户或组的用量,把结果记录到配额数据库文件中,通常位于挂载点根目录,文件名是aquota.user和aquota.group。这些文件本质上是索引化的用量记录表,quotacheck用来扫描文件系统并重建它们,quotaon则是告诉内核“从现在开始启用配额限制”。

而 XFS 文件系统的实现方式不一样。XFS 把配额信息直接写进文件系统的元数据中,不需要外部数据库文件,所以它的命令体系也完全不同,后面我会专门讲。理解这个差别很重要,很多人拿着 ext4 的流程去操作 XFS,结果一无所获。

2.5 ext4 与 XFS 的配额实现差异:先有个概念

现代主流发行版里,XFS 的使用率越来越高,xfs_quota 和传统 quota 工具是两套完全不同的操作体系。我建议你在动任何分区之前,先确认文件系统类型,不然很容易在错误的命令上浪费大量时间。下表是我整理的核心差异:

对比项ext4XFS
启用选项usrquota, grpquotausrquota, grpquota, prjquota
用量数据库aquota.user / aquota.group元数据内嵌,无独立文件
初始化操作quotacheck不需要
启用命令quotaonxfs_quota -x -c "enable -u"
主要管理命令edquota / setquotaxfs_quota
是否支持项目配额不原生支持支持,prjquota 方式

3. 开始前先确认环境:文件系统、挂载选项与工具安装

3.1 检查当前的挂载参数

不管用哪套工具,第一步都是确认目标分区的文件系统类型和当前挂载参数:

findmnt /home df -T /home

findmnt 的输出里会直接显示 FSTYPE 和 OPTIONS。比如ext4或者xfs,挂载选项里有没有usrquota、grpquota。第一次检查时多半是没有的,不用慌,接下来我们去加。

为什么要确认文件系统类型?因为后面是否启用 XFS 的 prjquota、是否运行 quotacheck,都取决于这一步。我踩过的最典型的坑就是:在 XFS 分区上跑了传统 quotacheck,结果工具直接报“无法处理该文件系统”,白白折腾了半天才发现系统默认根分区就是 XFS。

3.2 修改 fstab 并重新挂载

配额要生效,必须让文件系统在挂载时带上配额选项。最稳妥的方式是修改/etc/fstab:

UUID=xxxx-xxxx-xxxx /home ext4 defaults,usrquota,grpquota 1 2

注意几点:

  • 如果还要限制组,就加grpquota,不然加usrquota就够;
  • 根分区/也可以启用配额,fstab 对应行加上即可;
  • 改完先执行mount -a或者mount -o remount /home让配置生效,但fstab 一定要改好,否则下次重启就恢复到无配额状态。

改完之后再执行一次findmnt /home,看到 OPTIONS 里已经有usrquota就说明挂载参数生效了。此时先别急着操作,接下来装工具。

3.3 安装 quota 工具集

Debian/Ubuntu 系:

sudo apt update sudo apt install quota

RHEL/CentOS/Fedora 系:

sudo dnf install quota

装完后可以用quota --version验证。这个包通常还带quotacheck、edquota、setquota、repquota、warnquota等配套命令。如果是 XFS,包里面同样带了xfs_quota,不需要额外装别的东西。

3.4 确认内核配额模块

现代发行版的内核默认都编译了配额支持,一般情况下不需要额外加载模块。不过我习惯性检查一下,因为个别精简内核可能没有:

grep CONFIG_QUOTA /boot/config-$(uname -r)

如果输出里有CONFIG_QUOTA=y或者CONFIG_QUOTA=m,就说明内核支持配额。万一没找到,可以考虑换内核或确认当前内核是否适合生产用途,这属于比较极端的情况。

4. ext4 文件系统启用配额:完整命令链路与验证

4.1 初始化配额数据库:quotacheck

确认挂载选项已经包含usrquota后,对 ext4 系文件系统,第一步是生成配额数据库:

sudo quotacheck -avugm /home

参数拆开解释:

  • -a:扫描所有启用了配额的文件系统;
  • -u:检查用户配额;
  • -g:检查组配额;
  • -v:输出详细信息;
  • -m:即使文件系统以读写方式挂载,也强制重建配额文件。

这里-m很关键。默认情况下 quotacheck 会建议你把文件系统以只读方式挂载再扫描,但在生产环境里你不太可能为了扫一遍配额就去卸载分区。-m就是跳过这个限制,直接扫描。

扫描完成后,到挂载点下面确认一下:

ls -la /home | grep aquota

如果看到aquota.user和aquota.group,说明数据库已经生成。这两个文件是隐藏性质的普通文件,对应系统的配额记账底表。

4.2 编辑配额限制:edquota 与 setquota

接下来给用户设置配额值,最直观的工具是edquota:

sudo edquota -u testuser

命令会打开一个文本编辑器,内容类似:

Filesystem blocks soft hard inodes soft hard /dev/sda1 1204 20480 24576 10 0 0

需要修改的是soft和hard列。注意这里的 blocks 单位是 1KB,所以如果我想给 testuser 设 2GB 软限制、2.5GB 硬限制,那么 soft 写2097152,hard 写2621440。inodes 列则设置文件数量上限。

如果你不喜欢在编辑器里改,也可以用setquota一行搞定:

sudo setquota -u testuser 2G 2.5G 10000 15000 /home

参数顺序是:用户、软块、硬块、软 inode、硬 inode、挂载点。setquota支持K、M、G这样的单位后缀,写起来非常方便。这个命令最大的价值在于批量脚本化,后面会专门讲。

4.3 启用配额并查看结果:quotaon 与 quota

数据库建好、限制设好之后,启用配额:

sudo quotaon -avug

-a表示启用所有支持配额文件系统上的配额,-u用户,-g组。如果你只想启用某个挂载点,也可以明确指定:

sudo quotaon /home

启用后,用quota命令查看具体用户的用量:

quota -s testuser

-s表示 human-readable 输出,会直接显示成2.0G这样的形式,不用自己换算 KB。如果显示Disk quotas for user testuser (uid 1003),下面列出了当前用量和限制值,就说明配额已经在管这个用户了。

4.4 用 dd 写满测试验证硬限制是否真的硬

配额配完之后一定要实测,不能看了配置就认为万事大吉。我的验证方式很简单:创建一个测试用户,设软限制 200M、硬限制 300M,然后用 dd 向他的目录写入:

sudo dd if=/dev/zero of=/home/testuser/testfile bs=1M count=100

这步会正常完成,因为 100M 低于软限制。继续写:

sudo dd if=/dev/zero of=/home/testuser/testfile2 bs=1M count=200

如果配额生效,这条命令应该在写满硬限制时中断,并出现Disk quota exceeded的提示。如果它一路写完了,那说明配额没生效,需要按后面的排查链路重新检查。

还有一种情况:写入大小卡在软限制和硬限制之间,比如继续写 50M,内核会允许写入,但这会触发宽限期计时。我在测试时会专门写一个超过软限制但不到硬限制的文件来验证宽限期状态,确保后续用户超限时系统能做出正确响应。

4.5 查看全盘配额报表:repquota

当用户多了以后,一个个看 quota 效率太低。用repquota可以输出整个文件系统的配额汇总表:

sudo repquota -s /home

它会列出所有用户的当前用量、软限制、硬限制、剩余宽限期等。这个命令是日常巡检的主力。我一般配合 cron 定期把它输出到日志目录,方便回溯。

4.6 宽限期调整:edquota -t

默认宽限期是 7 天,如果你的业务场景不允许用户超限几天,也可以调短:

sudo edquota -t -u /home

同样会打开编辑器,把grace period改短,比如 1 天。组配额的宽限期用-g调整。注意宽限期是针对“超过软限制”的状态计时的,用户一降回软限制以下,计时就会重置。

5. XFS 文件系统:走进 xfs_quota 的世界

5.1 XFS 配额与传统工具有何不同

XFS 在现代发行版里非常常见,很多系统的根分区默认就是 XFS。XFS 与传统 ext4 配额的最大区别是:配额信息随文件系统元数据管理,不需要单独的 aquota 文件,也不需要 quotacheck。你如果在 XFS 分区上跑quotacheck,要么报错,要么什么都扫不出来。

XFS 挂载选项同样是在 fstab 中加usrquota和grpquota,也可以加上prjquota来支持项目配额。修改挂载方式跟 ext4 差不多,但后续管理命令完全不同,要靠xfs_quota。

5.2 xfs_quota 核心命令:limit / report / disable

设置用户配额:

sudo xfs_quota -x -c "limit -u bsoft=2g bhard=2.5g testuser" /home

这里的-x是进入专家模式,-c后面跟具体命令。limit -u表示限制用户,bsoft和bhard分别指软、硬块限制。如果还要限制 inode 数:

sudo xfs_quota -x -c "limit -u isoft=10000 ihard=15000 testuser" /home

查看用量报表:

sudo xfs_quota -x -c "report -u" /home

临时停用/重新启用配额:

sudo xfs_quota -x -c "disable -u" /home sudo xfs_quota -x -c "enable -u" /home

注意:不要在业务高峰随便 disable,一旦禁用,用户超限写入就不会被拦截,空间很快会被填满。

5.3 项目配额:针对目录树而不是用户的管控

XFS 还有一个 ext4 没有的能力:项目配额(prjquota)。它允许你给某个目录树设定独立上限,而不是按用户或组。比如/srv/data/project1这个目录最多给 20GB,不管谁往里写。

大致流程是:先给目录分配项目 ID,再通过 xfs_quota 设置项目配额:

sudo xfs_quota -x -c "project -s project1" /srv/data sudo xfs_quota -x -c "limit -p bsoft=18g bhard=20g project1" /srv/data

这属于进阶用法,适合共享目录、多租户业务目录这类场景。项目配额需要挂载时带prjquota选项,并且给目录设置项目标签,理解起来比用户配额稍复杂,但确实很实用。

5.4 与 ext4 配额的对照

我用一个简单的对照总结两套操作的核心差异:

操作ext4XFS
生成/重建配额数据quotacheck -avugm不需要
设置用户限制edquota -u 或 setquotaxfs_quota -x -c "limit -u ..."
查看用户用量quota -u testuserxfs_quota -x -c "report -u"
查询全盘报表repquota /homexfs_quota -x -c "report -u" /home
启用配额quotaon -avugxfs_quota -x -c "enable -u" /home

写到这里必须多说一句:不要凭记忆硬套命令。XFS 专家模式下命令语法非常灵活,不同发行版的xfs_quota版本也有细微差别,配置前先xfs_quota -x -c "help"看一眼当前版本支持的关键字。

6. 多人环境下批量落地:模板复制、脚本批量 setquota 与自动监控

6.1 edquota -p 复制模板

给一个用户配好配额后,其他人员可以直接复制他的配置。最方便的方式是用edquota -p:

sudo edquota -p testuser user1

这会把 testuser 的配额模板原样复制给 user1。如果一批新人入职,可以一次指定多个:

sudo edquota -p testuser user1 user2 user3

这个命令省去了手工编辑的麻烦,但它的局限在于:所有被复制的人拿到的是完全一致的配额,如果每人需求不同,还需要再微调。

6.2 setquota 配合循环脚本批量配置

当你需要给一批人设置不同配额时,setquota配合脚本是最灵活的。我常用的做法是准备一个用户列表文件,每行格式是“用户名 软块 硬块 软inode 硬inode”,然后用循环去设置:

while read user softB hardB softI hardI; do sudo setquota -u "$user" "$softB" "$hardB" "$softI" "$hardI" /home echo "quota set for $user" done < /tmp/quota_list.txt

注意这里的softB和hardB如果写5G、6G这样的带单位值,setquota 是可以直接识别的。这个脚本还有个好处:你可以在执行前加一个quotaoff再统一quotaon,避免用户量大的时候某些配置还没来得及生效。

6.3 自动配额报表生成方案

配额配好只是开始,日常监控才重要。我通常用 cron 每天生成一次磁盘配额报表:

sudo crontab -e

加入一行:

0 1 * * * /usr/sbin/repquota -s /home > /var/log/quota_report_$(date +\%F).txt 2>&1

这样每天凌晨 1 点自动生成一份带日期的报表文件。想更省事的话,还可以加个半分钟扫描逻辑,用脚本判断某些用户的使用率是否超过 90%,达到阈值就往管理邮箱发通知。这种告警脚本的粒度可以根据业务需要调整,但有个原则是:告警要早于硬限制,别等用户已经写不进去了才通知。

6.4 配额告警与人工介入的边界

自动报表能告诉你“谁用了多少”,但真正的清理动作往往还是需要人工介入。配额机制本身不会帮用户删除任何文件,它只是在用户写入时给予拦截。所以我在团队里制定了简单规则:用户被硬限制挡住后,优先自己清理旧文件;如果确定是临时需求,管理员可以临时把硬限制调高一档,几小时后还原。这个操作流程既保证了磁盘可控,也避免了频繁向管理员求助。

7. 实测踩坑记录:配额不生效、宽限期失效等问题的排查链路

7.1 配额未生效的排查步骤

如果你设置了配额,但测试发现用户照样可以写爆,按这个顺序排查:

  1. 确认文件系统类型:ext4 还是 XFS,命令是否用对;
  2. 确认挂载选项:findmnt看有没有usrquota/grpquota或prjquota;
  3. 确认配额数据库存在:ext4 检查aquota.user,XFS 不用管这步;
  4. 确认配额已启用:XFS 用xfs_quota -x -c "state -u",ext4 用quotaon -p;
  5. 确认用户 quota 值不是 0:如果 soft 和 hard 都是 0,表示没有限制;
  6. 实测写入,而不是只盯着配置文件看。

有一次我在某开发环境上折腾了半天,最后发现是挂载选项只在命令行 remount 了,fstab 没改。表面看配额已经在工作,但设备一重启就全部失效。这种“看起来有效,重启原形毕露”的坑,比直接没生效更隐蔽。

7.2 重启后配额失效的真相

配额失效重启后的原因几乎都是同一个:/etc/fstab里缺少配额挂载选项。mount -o remount,usrquota只对当前运行时有效,重启后内核还是会按 fstab 里的参数重新挂载。正确做法就是改 fstab,然后mount -a验证。

另外,部分老旧的系统脚本里会靠quotaon -avug的开机自启,但新一点的 systemd 环境下,quota 包本身就带了 quotaon.service。如果你发现开机后配额没有自动启用,可以执行:

systemctl status quotaon

如果服务不是 enabled 状态,就启用它:

sudo systemctl enable --now quotaon

7.3 XFS 上跑 quotacheck 的无效操作

这个问题真的很常见。看到服务器 /home 是 XFS,还习惯性执行quotacheck -avugm,结果报错或者卡住。记住:XFS 不需要、也不支持传统 quotacheck。它的配额数据靠挂载选项和 xfs_quota 管理。你只需要确认挂载选项里带了usrquota,然后用xfs_quota -x -c "state"查看状态即可。

7.4 配额数据库文件丢失与重建

ext4 系列的 aquota 文件如果被人删了,或者系统异常重启导致配额文件损坏,quotaon会提示找不到配额文件。解决办法是重建:

sudo quotaoff -avug sudo rm -f /home/aquota.user /home/aquota.group sudo quotacheck -avugm sudo quotaon -avug

注意顺序是先停用再删除,最后重建。重建后所有用户的软硬限制配置是无的,需要重新设置,所以生产环境最好把配额模板用脚本保存下来,比如在注释里写明每个用户的配额值。

7.5 根分区启用配额的特殊性

根分区/也可以启用配额,但在操作时有几个细节需要注意:根分区不能随便卸载,所以 remount 要特别小心;如果根分区是 ext4,建议先确保系统有足够空间,再执行quotacheck -m;如果是 XFS,确认内核和工具版本支持即可。另外,root 用户的配额默认不受限制(uid 0 绕过配额检查),这是内核设计上的保护机制,不用觉得奇怪。

做根分区配额时我还遇到过一个问题:根挂载点下的aquota.user文件在后续系统升级或日志写入中容易被改动,导致配额状态异常。所以我现在的习惯是:能不做根分区就尽量不做根分区,只对/home、/srv、/data这样的数据分区做配额,既满足管理需求,又降低了系统层被误伤的风险。

最后再分享一个小技巧:在群组协作环境里,我习惯把所有配额配置写成一份可执行的 shell 脚本放在管理员 home 目录下,脚本里包含用户名列表和对应的 soft/hard 值。这样不管是新机器搬迁、还是磁盘扩容后重新初始化,都能在几分钟内把配额策略完整还原,而不是靠记忆一个个手敲。配额管理这东西,配置一次不难,难的是可重复、可维护。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进