site logo

Marico's space

告别SSD性能衰减:Linux fstrim.timer实战指南

AI技术与应用 2026-05-07 17:37:36 1

别让SSD性能腐烂:Linux上实用的fstrim.timer

如果你的Linux系统运行在SSD、由SSD存储支持的虚拟磁盘或精简配置卷上,TRIM是那种容易被遗忘、日后调试又很麻烦的无聊维护任务。

好消息是,现代Linux已经有了一个明智的解决方案:fstrim.timer

本文展示如何:

  • 验证discard是否真正被支持
  • 检查fstrim.timer是否已启用
  • 安全地启用每周TRIM计划任务
  • 在需要时手动运行trim
  • 避免一个常见错误——挂载时使用持续discard

我这里聚焦于实用路径,而非存储领域的陈旧观念。

TRIM实际做了什么

当文件被删除时,文件系统知道这些块是空闲的,但SSD可能不会立即知道。通过Linux上的fstrim暴露的TRIM会告诉底层存储哪些未使用的块可以被丢弃。

这很重要,因为:

  • SSD性能一致性
  • 某些精简配置存储后端
  • 在某些虚拟化平台上更准确地回收空间

fstrim(8)手册描述得很清楚:fstrim会丢弃已挂载文件系统上未使用的块,对SSD和精简配置存储很有用。

为什么`fstrim.timer`通常比`discard`更好

很多指南直接建议在挂载选项中添加discard。这不是我的默认建议。

上游fstrim(8)手册页明确警告:频繁运行TRIM,或使用mount -o discard,可能会对质量较差的SSD产生负面影响,并指出对于大多数桌面和服务器系统,每周一次就足够了。

这与当今许多发行版的默认配置一致。在本机上,打包的timer是:



# /usr/lib/systemd/system/fstrim.timer
[Timer]
OnCalendar=weekly
AccuracySec=1h
Persistent=true
RandomizedDelaySec=100min

这是一个非常合理的默认值:

  • weekly保持适度的执行频率
  • Persistent=true意味着错过的运行会在启动后补上
  • RandomizedDelaySec=在多台机器间分散负载

步骤1:检查存储是否声明支持discard

lsblk -D开始:



lsblk -D

示例输出:


NAME    DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
vda            0      512B       2G         0
├─vda1         0      512B       2G         0
├─vda14        0      512B       2G         0
└─vda15        0      512B       2G         0

需要关注的内容:

  • DISC-GRANDISC-MAX不应同时为0B
  • 非零的discard值表明块设备可以接受discard/TRIM请求

你也可以用以下命令检查已挂载的文件系统:



findmnt -D

这会给你一个已挂载文件系统和discard相关设备特性的快速视图。

步骤2:检查timer是否已存在并处于活动状态

很多系统已经默认启用了。在做任何更改之前先检查:



systemctl status fstrim.timer
systemctl list-timers --all fstrim.timer

示例:


NEXT                          LEFT LAST                            PASSED UNIT         ACTIVATES
Mon 2026-05-11 00:46:45 UTC 3 days Mon 2026-05-04 01:29:37 UTC 3 days ago fstrim.timer fstrim.service

如果你看到下次运行已安排,你可能已经完成了。

你也可以检查打包的service和timer定义:



systemctl cat fstrim.timer fstrim.service

在这台机器上,service执行的是:



ExecStart=/sbin/fstrim --listed-in /etc/fstab:/proc/self/mountinfo --verbose --quiet-unsupported

这是个很好的细节。它会trim fstab或挂载信息中列出的文件系统,打印有用的字节数,并对不支持的文件系统抑制烦人的错误。

步骤3:启用并启动timer

如果timer已安装但未激活,启用它:



sudo systemctl enable --now fstrim.timer

然后确认:



systemctl status fstrim.timer
systemctl list-timers --all fstrim.timer

如果你的发行版使用了厂商预设已启用它,这个命令是无害的。

步骤4:手动运行一次性TRIM

有时候你不想等到每周运行,特别是刚完成大清理、VM镜像压缩或容器/镜像修剪之后。

运行:



sudo fstrim -av

参数含义:

  • -a trim所有支持该操作且已挂载的文件系统
  • -v 显示有多少字节被向下传递以供可能丢弃

示例输出通常如下:


/: 38.2 GiB (41016926208 bytes) trimmed
/boot/efi: 97.5 MiB (102236160 bytes) trimmed

fstrim(8)有一个微妙但重要的说明:报告的字节数是向下传递以供可能丢弃的数量,而不是保证设备当时确实物理丢弃了每个字节。这是正常的。

步骤5:验证上次运行和日志

无论是手动运行还是timer驱动的运行之后,检查service日志:



systemctl status fstrim.service
journalctl -u fstrim.service --since "7 days ago"

这给你两样有用的东西:

  • service是否实际成功
  • 哪些挂载点被trim了以及报告了多少

何时不应期望这能工作

有几个情况会让人踩坑:

1. 你在容器内部

在这台主机上,打包的unit包含:



ConditionVirtualization=!container

所以fstrim.timerfstrim.service在容器内会被故意跳过。这是正确的,因为discard属于拥有块设备的主机或VM层。

2. 文件系统或块层不支持discard

fstrim(8)手册页指出,在trim所有文件系统时,不支持的文件系统和只读情况会被忽略。如果你的存储栈不传递discard,再多的systemd调整也解决不了。

3. 你在使用旧建议,认为必须实时挂载`discard`

这通常已不再是问题。每周批量TRIM是大多数系统的上游推荐默认值。

大多数Linux机器的安全基线

如果我要在一台普通工作站、家庭服务器或由SSD存储支持的VM上配置这个,我的基线会是:



lsblk -D
findmnt -D
systemctl status fstrim.timer || true
sudo systemctl enable --now fstrim.timer
sudo fstrim -av
journalctl -u fstrim.service --since today

这样你就能获得:

  • 能力检查
  • timer状态
  • 已安排的持续维护
  • 一次立即清理运行
  • 验证痕迹

你应该把`discard`添加到`/etc/fstab`吗?

通常不要。

只有当你的存储栈确实受益于即时回收,并且你已经测试过性能权衡的情况下,我才会考虑持续discard。对于通用Linux系统,每周timer是更干净的默认值。

最终总结

fstrim.timer是Linux中那些罕见的同时既无聊又正确的默认配置之一。

如果你的存储支持discard,启用timer,验证一次,然后继续你的生活。这比把discard胡乱添加到每个挂载选项并希望最好要好得多。

参考资料

  • fstrim(8)手册页:https://man7.org/linux/man-pages/man8/fstrim.8.html
  • systemd fstrim.timer手册:https://www.freedesktop.org/software/systemd/man/latest/fstrim.timer.html
  • Fedora关于启用fstrim.timer的变更说明:https://fedoraproject.org/wiki/Changes/EnableFSTrimTimer
  • lsblk(8)手册页:https://man7.org/linux/man-pages/man8/lsblk.8.html
  • findmnt(8)手册页:https://man7.org/linux/man-pages/man8/findmnt.8.html