ZFS 快照:如何创建、还原和自动操作快照
10 分钟阅读 - 2026年5月5日

学习如何在 Linux 上创建、还原和自动化 ZFS 快照。包括命令、回滚、保留策略和使用 Sanoid 进行异地复制。
ZFS 快照:如何创建、还原和自动化快照
ZFS 快照是文件系统的只读、时间点副本。它是即时创建的,在数据发生变化之前不占用任何空间,可让你在几秒钟内回滚或恢复文件。如果你要管理服务器、VPS 实例或任何你不能丢失的数据,快照应该成为你工作流程的一部分。
本篇文章将介绍 ZFS 快照的工作原理、使用方法以及如何自动保留快照,以免快照堆积如山。
ZFS 快照的工作原理
ZFS 采用写入时复制(CoW)模式。拍摄快照时,ZFS 不会复制任何数据。它只是记录块指针树的当前状态。新的写入将进入空闲区块,而快照将继续引用原始数据。
这意味着,无论数据集大小如何,快照都能在几微秒内创建,而且在创建时不会占用额外空间。只有当实时数据集发生变化时,快照才会开始占用空间,因为快照会保留原本会被释放的原始块。
这与rsync或tar 等扫描和复制整个文件的文件级备份工具有本质区别。如果你更改了 10GB 文件中的 4KB,rsync 会复制整个文件。而 ZFS 只保存 4KB 的数据块。
快照也是不可变的。快照在内核级被强制为只读,因此用户空间进程(包括勒索软件)无法修改快照。再加上 ZFS 内置的校验和,这意味着你可以在还原时验证数据的完整性。
创建快照
前提条件
您需要安装 ZFS 并设置一个池。在 Ubuntu 20.04+ 上:
sudo apt update && sudo apt upgrade -y
sudo apt install zfsutils-linux -y
sudo modprobe zfs创建一个池。对于单个磁盘(VPS 上的典型情况):
sudo zpool create tank /dev/sdb对于专用服务器上的镜像设置,请使用磁盘 ID 而不是设备名称,以避免重启后出现问题:
sudo zpool create tank mirror /dev/disk/by-id/ata-DISK1 /dev/disk/by-id/ata-DISK2启用压缩(LZ4 快速有效):
sudo zfs set compression=lz4 tank然后为工作负载创建数据集:
sudo zfs create tank/web
sudo zfs create tank/databases拍摄快照
基本命令
sudo zfs snapshot tank/web@before-update对于有时间戳的名称(对 cron 很有用):
sudo zfs snapshot tank/db@$(date +%Y%m%d_%H%M%S)要一次性捕获所有子数据集,请使用递归标志:
sudo zfs snapshot -r tank@daily_backup验证:
sudo zfs list -t snapshot从快照恢复
恢复单个文件
每个 ZFS 数据集的挂载点都有一个隐藏的.zfs/snapshot目录。它不会显示在ls 中,但你可以直接导航到它:
ls /tank/web/.zfs/snapshot/before-update/恢复单个文件
cp -p /tank/web/.zfs/snapshot/before-update/config/app.conf /tank/web/config/-p标记会保留权限和时间戳。
回滚整个数据集
如果需要恢复所有数据集,例如在升级失败后:
sudo zfs rollback tank/web@before-update这几乎是瞬间完成,因为 ZFS 更新的是块指针,而不是复制数据。但这是破坏性的:快照后所做的所有更改都会永久丢失。
如果在目标和当前状态之间存在更新的快照,ZFS 会阻止回滚。使用-r强制回滚并删除这些中间快照:
sudo zfs rollback -r tank/db@20260426_090000一个好习惯:在回滚之前先给当前(已损坏)状态拍快照,这样在需要时就有了后备方案。
| 恢复方法 | 恢复速度 | 数据丢失风险 | 最适合 |
|---|---|---|---|
通过.zfs恢复文件 | 取决于文件大小 | 无 | 意外删除、单个文件恢复 |
| 完全回滚 | 即时 | 高(丢失快照后的所有更改) | 升级失败、全系统问题 |
| 克隆测试 | 即时 | 无(创建并行数据集) | 在提交回滚之前进行验证 |
管理和修剪快照
快照从零大小开始,但会随着快照下实时数据的变化而增长。检查空间使用情况:
zfs list -t snapshot -o name,used,refer,creationUSED列显示该快照独有的空间大小。REFER显示拍摄快照时数据集的总大小。
要删除快照
sudo zfs destroy tank/web@before-update也可以按模式删除:
sudo zfs destroy tank/web@daily-2026-04-%总是先进行干运行:
sudo zfs destroy -nv tank/web@daily-%从技术上讲,ZFS 可以处理数百万个快照,但每个数据集超过几千个快照后,性能就会下降。zfs list和zfs destroy等命令的运行速度会明显减慢。严格保留快照。
使用 Sanoid 实现自动保留
Sanoid是自动创建和修剪 ZFS 快照的标准工具。您可以在sanoid.conf 中定义保留策略,剩下的就交给它来处理。
典型的生产配置如下
| 工作负载类型 | 每小时 | 每日 | 每周 | 每月 |
|---|---|---|---|---|
| 标准生产 | 24-48 | 30 | 8 | 12 |
| 数据库(高流失率) | 72 | 30 | 12 | 24 |
| 日志/低优先级 | 12-24 | 7 | 0 | 3 |
| 静态媒体 | 0 | 7 | 0 | 3 |
Sanoid 还通过frequent参数支持每小时一次的快照。设置frequently = 96,frequent_period = 15,就可以每 15 分钟创建一次快照。
通过 cron 安排 Sanoid 每分钟或每 15 分钟运行一次,它就会自动创建和修剪快照。
使用 zfs 发送异地复制
单台服务器上的快照可以防止意外更改和软件故障,但不能防止硬件丢失。为此,可通过 SSH 使用zfs 发送和zfs 接收进行异地复制:
zfs send tank/web@backup | ssh user@remote zfs receive backup/web用于增量传输(只发送上次快照后发生变化的内容):
zfs send -i tank/web@old_snap tank/web@new_snap | ssh user@remote zfs receive backup/webSanoid 的配套工具syncoid 可自动完成这一过程,并处理增量发送、错误恢复和日志记录。
关于勒索软件保护的说明
ZFS 快照在内核级别是只读的,这意味着标准恶意软件无法修改或加密它们。这是一个强大的防御层。但它并非刀枪不入:如果攻击者获得 root 访问权限,他们可以在加密你的数据前删除快照。
快照应该是更广泛战略中的一层。将快照与异地复制、限制根访问和网络级安全结合起来。不要仅仅依赖快照。
视频推荐

ZFS 快照:如何创建、还原和自动操作快照
学习如何在 Linux 上创建、还原和自动化 ZFS 快照。包括命令、回滚、保留策略和使用 Sanoid 进行异地复制。
10 分钟阅读 - 2026年5月5日
如何在 VPS 上安装和使用 Redis
9 分钟阅读 - 2026年1月7日