ext4 挂载参数与 tune2fs 调优实战:noatime、SSD TRIM、预留块与文件系统自检策略全流程

你的 ext4 还开着一堆十年前的默认参数

大部分 Linux 云服务器装完系统,/etc/fstab 里根分区的挂载参数就是默认的 defaults。这个 defaults 展开后是 rw,suid,dev,exec,auto,nouser,async——一套兼容性优先、性能和安全都不是最优的设置。很多站长从来没碰过它,于是服务器常年带着 relatime(甚至 atime)在跑,SSD 上的 TRIM 没开,损坏检查的频率还是二十年前的标准。

这篇文章把 ext4 的挂载参数、tune2fs 的调优、以及定期文件系统自检的实战讲一遍。改这些不需要重装系统、不需要迁移数据,改完重新挂载即可生效,是「零成本换性能」的典型。

先看清当前挂载参数

mount | grep ext4
# /dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro)
# 或者更清晰地逐个设备看
findmnt -t ext4 -o TARGET,SOURCE,FSTYPE,OPTIONS

重点看几个参数:有没有 noatime、有没有 discard、有没有 nodiratime。如果只看到 relatime(大多数发行版的默认),说明还有优化空间。

atime 三兄弟:noatime 到底省了什么

ext4 默认记录三种时间:mtime(内容修改时间)、ctime(inode 修改时间)、atime(访问时间)。每次读文件,内核都要更新 atime——这意味着一堆额外的写操作:读文件本来只是读,却要写回一次 inode。

Linux 后来引入了 relatime:只在 atime 早于 mtime/ctime,或者超过一天没更新时才写。这是个折中,但仍然是写操作。对高并发读的网站,最彻底的是 noatime——完全关闭 atime 更新。

# fstab 里把 defaults 换成:
UUID=xxxx / ext4 defaults,noatime,nodiratime,errors=remount-ro 0 1

nodiratime 是不更新目录的 atime,noatime 已经包含了它的效果,两者一起写只是明确意图。改完 mount -o remount / 立即生效,不用重启。

代价是:find -atime、某些备份工具的「按访问时间」策略、以及 maildir 之类的软件(依赖 atime 判断已读)可能受影响。对纯网站服务器来说,这个代价可以忽略。

discard 与 SSD:TRIM 的两条路

SSD 需要 TRIM 才能长期保持性能。ext4 有两种开法:

  • 挂载参数加 discard:每次删除文件立即发 TRIM 命令。简单,但每次删除都同步发命令,可能造成小的延迟抖动。
  • 定时 fstrim:不挂 discard,改用 fstrim 周期性批量 TRIM(systemd 已经内置了 fstrim.timer,默认每周一次)。

我更推荐定时 fstrim,因为它把 TRIM 的 IO 集中到低峰期,不影响高峰期删除操作的延迟。确认它开着:

systemctl status fstrim.timer
# 手动跑一次看看能回收多少
fstrim -v /

如果云服务商的虚拟磁盘不支持 TRIM(很多云盘不支持),fstrim 会提示 the discard operation is not supported,这是正常的,忽略即可,不要硬上 discard 参数。

其他值得调的挂载参数

参数作用适用
noatime不更新访问时间,减少写所有高读负载站点
nodiratime不更新目录访问时间已含在 noatime
data=ordered数据先于元数据落盘(ext4 默认)保持默认最安全
errors=remount-ro出错时只读挂载,防止数据继续损坏推荐
nobarrier关闭写屏障,换取性能有掉电风险,慎用

data=writeback 比 ordered 更快,但崩溃后可能读到「新元数据 + 旧数据」的不一致,对生产环境不值得冒险,保持 ordered 就好。nobarrier 只在下层存储自己有掉电保护(比如带电池的 RAID 卡)时才考虑。

tune2fs:调文件系统本身的行为

挂载参数是运行时行为,tune2fs 调的是文件系统内部结构。几个关键项:

1. 预留块比例(reserved blocks)

ext4 默认给 root 预留 5% 的磁盘空间,防止用户写满后系统无法操作。但现在的服务器动辄几百 G,5% 就是几十 G 白白浪费。对非根分区(比如专门放网站数据的分区),可以调小:

tune2fs -m 1 /dev/sdb1   # 预留比例降到 1%

根分区建议保留 1%~2%,数据分区可以降到 0(但要注意写满后无法写日志的风险)。tune2fs -l /dev/sdb1 | grep -i reserved 可以确认。

2. 挂载次数与自检间隔

ext4 传统上会在挂载 N 次或每 M 天做一次 fsck。对大分区,一次 fsck 可能几十分钟甚至几小时。现代 SSD + 日志文件系统下,每次挂载自检已经没必要:

# 关掉「挂载 N 次后自检」
tune2fs -c 0 /dev/sda1
# 或者设为一个很大的次数
tune2fs -c 100 /dev/sda1
# 设置自检的最长间隔(天)
tune2fs -i 180d /dev/sda1

把次数设为 0 表示不再按次数触发,只保留按时间(180 天)。这样既避免了频繁 fsck,又保留了定期健康检查。

3. 查看文件系统状态

tune2fs -l /dev/sda1

输出里的 Filesystem state: clean 表示正常,如果是 not clean 说明上次没正常卸载。还有 Mount count、Maximum mount count、Last checked、Lifetime writes(这一项对 SSD 寿命评估有用,单位一般是 GB)。

fsck:什么时候该检查,怎么检查

ext4 是日志文件系统,正常情况下崩溃后靠日志回放就能恢复一致性,不需要全盘 fsck。真正需要 fsck 的场景是:硬件报错、内核日志出现 EXT4-fs error、或者 tune2fs 显示 not clean。

# 只读检查(不修),必须卸载分区或用 -n
fsck.ext4 -n /dev/sda1
# 实际修复,必须在卸载状态(根分区要在救援模式或 rescue.target)
fsck.ext4 -f -y /dev/sda1

注意:绝不能在已挂载的分区上跑修复,会彻底损坏数据。根分区要在单用户模式或救援模式下操作。日常的定期检查交给 e2scrub(ext4 的空闲检查工具)比盲目 fsck 更安全,它在 LVM 快照上做只读检查,不影响运行中的文件系统。

用 e2scrub 做在线只读检查

# 检查 ext4 是否需要 scrub(依赖 LVM)
e2scrub_all -A   # 检查所有
# systemd 里可以启用定时任务
systemctl enable --now e2scrub_all.timer

目录索引(dir_index)与大目录性能

ext4 默认开启了 dir_index,用 HTree 索引加速大目录查找。但很多站长把几万个文件堆在一个目录里(比如缓存目录、图片目录),即使有索引,ls 和创建文件依然慢。检查特性是否开启:

tune2fs -l /dev/sda1 | grep features
# 应该看到 dir_index 在列表里

如果没开,tune2fs -O dir_index /dev/sda1 可以开启(需要 fsck 重建索引)。不过更好的做法是从根上避免单目录文件过多——缓存文件按哈希或日期分目录,是内容站常见的优化手段。

大目录与 inode 预留:两个容易被忽略的 mkfs 决策

挂载参数是「运行时」调优,但有些东西在建文件系统那一刻(mkfs)就定死了,事后只能重建。最常见的一个是 inode 数量。ext4 默认按每 16KB 数据分配一个 inode(bytes-per-inode=16384),意味着 1TB 分区大约能建 6700 万个文件。对存放大量小文件的站点(图片缩略图、缓存碎片、session 文件),这个数量可能不够,会出现「磁盘还有空间但 inode 耗尽」写不进去的经典故障。

检查 inode 使用情况:

df -i
# Filesystem      Inodes   IUsed   IFree IUse% Mounted on
# /dev/sda1      6553600  412000 6141600    7% /

如果 IUse% 接近 100% 而 df -h 空间还剩很多,就是 inode 不足。mkfs 时用 -i 或 -N 控制:

mkfs.ext4 -N 10000000 /dev/sdb1   # 直接指定 inode 总数
mkfs.ext4 -i 8192 /dev/sdb1        # 每 8KB 一个 inode(数量翻倍)

代价是 inode 本身占空间,小分区把 inode 调太多会浪费。对内容站来说,按默认值通常够用,但如果你的站点有海量缩略图、或者跑着邮件系统(maildir 单文件存信),建库时就该把 inode 调大。

stride 与 stripe_width:RAID 上的对齐优化

如果文件系统建在 RAID 阵列之上(硬 RAID 或软 RAID),mkfs 时的 stride 和 stripe-width 参数会影响性能。原理是让 ext4 的块分配器按 RAID 条带对齐,避免一个写操作跨多个磁盘造成读改写惩罚:

# 假设 RAID5 有 6 块盘,chunk 大小 64KB
# stride = chunk / block_size = 64KB / 4KB = 16
# stripe-width = stride * (盘数 - 1) = 16 * 5 = 80(RAID5 校验盘不算)
mkfs.ext4 -E stride=16,stripe-width=80 /dev/md0

参数算错反而可能更慢,所以只在确认 RAID 配置时才用。单盘或云盘环境直接忽略。这也是「建库前想清楚」的典型——建完再改就来不及了。

journal 模式与日志大小

ext4 的日志(journal)记录元数据变更,崩溃后靠它回放恢复一致性。日志有两种常用模式,通过挂载参数 data= 选择(前面表格提过默认是 ordered)。此外,日志文件本身的大小也影响性能——太小会导致频繁提交,太大会占用额外空间、延长恢复时间。默认日志大小是 128MB 左右(对大分区),可以用 tune2fs 查看和调整:

# 查看日志大小
tune2fs -l /dev/sda1 | grep -i "journal size"
# 调整日志大小(需要在卸载状态下,且会重建日志)
tune2fs -J size=256 /dev/sda1

对绝大多数站点,默认日志大小就够了,没必要动。只有在高写入负载(比如频繁小文件写入)且实测有 journal 相关瓶颈时,才考虑调整。调大日志会占用更多空间,收益不总是明显。

用 findmnt 和 lsblk 建立存储全貌

调优之前,先要知道自己的存储是什么结构。两个命令足够:

# 树形展示块设备、分区、挂载点
lsblk -f
# 输出含 FSTYPE、UUID、MOUNTPOINT,一眼看清哪个分区挂在哪
findmnt -t ext4,xfs -o TARGET,SOURCE,FSTYPE,OPTIONS,SIZE,USE%

lsblk -f 特别适合排查「我以为数据在 /data,结果它其实是根分区的一个目录」这类问题。很多站长换服务器时发现磁盘空间对不上,往往就是分区规划和使用实际不一致。findmnt 的 -o 可以自定义输出列,把 OPTIONS 列出来,就是前面说的「当前挂载参数」检查。

多久维护一次文件系统

文件系统不是「配完就忘」的东西。建议的节奏:

  • 每周:检查 df -h 和 df -i,确认空间和 inode 都没告急;tune2fs -l | grep -i "filesystem state" 确认 clean。
  • 每月:跑一次 fstrim -v / 看 TRIM 是否正常(如果适用),检查 SMART 健康度。
  • 每半年:用 e2scrub_all 做一次在线只读检查,或者计划一次离线 fsck(低峰期、有备份)。
  • 出问题时:内核日志出现 EXT4-fs error 或 remount-ro 才是真需要 fsck 的信号,别没事找事。

改完怎么验证

# 重新挂载使 fstab 生效(无需重启)
mount -o remount / 
# 确认参数已变
findmnt -t ext4 -o TARGET,FSTYPE,OPTIONS
# 确认预留块
tune2fs -l /dev/sda1 | grep -i "reserved block count"
# 确认自检策略
tune2fs -l /dev/sda1 | grep -i "mount count"

注意事项与踩坑

  • 改 fstab 前先备份:fstab 写错会导致系统起不来。改前 cp /etc/fstab /etc/fstab.bak,改完先用 mount -o remount 测,别急着重启。
  • UUID 别用设备名:fstab 里用 UUID= 而不是 /dev/sda1,防止网卡/磁盘顺序变化导致挂载错盘。
  • reserved blocks 别设 0:根分区设为 0 后,一旦写满,系统连日志都写不了,可能彻底卡死。至少留 1%。
  • 别用 discard 参数叠 fstrim.timer:两者会重复 TRIM,虽然不致命但没必要。
  • noatime 影响备份策略:如果备份工具依赖 atime 判断哪些文件被访问过,改用 mtime 或直接全量。
  • XFS 用不了 tune2fs:XFS 有自己的 xfs_admin 和 xfs_growfs,命令完全不同,别照搬。

结语

文件系统调优是那种「改一次受益很久」的事情。noatime 减少无谓的写、fstrim 保持 SSD 性能、tune2fs 把预留块和自检策略调到符合实际的规模——这些改动加起来,能让一个长期运行的网站在磁盘层面少踩很多坑。关键是别一次全改,改一项验证一项,尤其是涉及 fstab 和根分区的操作,务必留好回滚路径。对个人站长来说,把 defaults 换成一份经过考量的挂载参数,往往比升级硬件更立竿见影。

Last modification:October 11th, 2026 at 01:25 pm

Leave a Comment