Snapper
Snapper 是由 openSUSE 的 Arvin Schnell 创建的一个工具,用于管理 Btrfs 子卷、精简配置的 LVM 卷,以及(实验性地)Bcachefs 子卷的快照。它可以创建和比较快照,在快照之间回滚,并支持自动快照时间线。
安装
此外,还有可用的 GUI,例如 btrfs-assistant、snapper-gui-gitAUR 和 snapper-toolsAUR。
创建新配置
在为 Btrfs 子卷创建 snapper 配置之前,该子卷必须已存在。如果不存在,您应该在生成 snapper 配置之前创建它。
要为位于 /path/to/subvolume 的 Btrfs 子卷创建名为 config 的新 snapper 配置,请运行
# snapper -c config create-config /path/to/subvolume
这将
- 在
/etc/snapper/configs/config创建一个配置文件,该文件基于/usr/share/snapper/config-templates中的默认模板。 - 在
/path/to/subvolume/.snapshots创建一个子卷,未来此配置的快照将存储在此。快照的路径是/path/to/subvolume/.snapshots/#/snapshot,其中#是快照编号。 - 将
config添加到/etc/conf.d/snapper中的SNAPPER_CONFIGS。
例如,要为挂载在 / 的子卷创建配置文件,请运行
# snapper -c root create-config /
@.snapshots 子卷将已挂载到 /.snapshots,并且 snapper create-config 命令将失败 [2]。要将 @.snapshots 子卷用于 Snapper 备份,请执行以下操作:- 卸载
@.snapshots子卷并删除现有的挂载点。 - 创建 Snapper 配置。
- 删除 Snapper 创建的子卷。
- 重新创建
/.snapshots挂载点并重新挂载@.snapshots子卷。
对于 archinstall 版本 3.0.5 或更高版本的建议 Btrfs 分区布局,则不需要此过程。
此时,配置已激活。如果您的 cron 守护进程正在运行,snapper 将会创建 #自动时间线快照。如果您不使用 cron 守护进程,则需要使用 systemd 服务和计时器。请参阅 #启用/禁用。
另请参阅 snapper-configs(5)。
拍摄快照
自动时间线快照
可以使用可配置数量的小时、日、周、月和年快照来创建快照时间线。当启用时间线时,默认情况下每小时创建一个快照。每天,快照会被时间线清理算法清理。有关详细信息,请参阅 snapper-configs(5) 中的 TIMELINE_* 变量。
启用/禁用
如果您有 cron 守护进程,此功能应该会自动启动。要禁用它,请编辑与您不想启用此功能的子卷对应的配置文件,并设置
TIMELINE_CREATE="no"
如果您没有 cron 守护进程,您可以使用提供的 systemd 单元。启动并启用 snapper-timeline.timer 来启动自动快照时间线。此外,启动并启用 snapper-cleanup.timer 来定期清理旧快照。
设置快照限制
默认设置将保留 10 个小时快照、10 个日快照、10 个月快照和 10 个年快照。您可能希望在配置文件中更改此设置,尤其是在 / 等繁忙的子卷上。请参阅 #防止速度下降。
以下是一个名为 config 的配置的示例部分,仅包含 5 个小时快照、7 个日快照,没有月快照和年快照
/etc/snapper/configs/config
TIMELINE_MIN_AGE="1800" TIMELINE_LIMIT_HOURLY="5" TIMELINE_LIMIT_DAILY="7" TIMELINE_LIMIT_WEEKLY="0" TIMELINE_LIMIT_MONTHLY="0" TIMELINE_LIMIT_YEARLY="0"
更改快照和清理频率
如果您使用的是提供的 systemd 计时器,您可以编辑它们以更改快照和清理频率。
例如,在编辑 snapper-timeline.timer 时,添加以下内容使其频率为每五分钟一次,而不是每小时一次
[Timer] OnCalendar= OnCalendar=*:0/5
编辑 snapper-cleanup.timer 时,您需要更改 OnUnitActiveSec。要使清理每小时发生一次,而不是每天一次,请添加
[Timer] OnUnitActiveSec=1h
请参阅 systemd/Timers 和 systemd#Drop-in 文件。
手动快照
单个快照
默认情况下,snapper 创建的是 *单个* 类型的快照,与其他快照没有特殊关系。
要手动拍摄子卷的快照,请执行
# snapper -c config create --description desc
上面的命令不使用任何清理算法,因此快照将被永久存储,直到删除为止。
要设置清理算法,请在 create 之后使用 -c 标志,并选择 number、timeline、pre 或 post。number 设置 snapper 定期删除已超过配置文件中设定的数量的快照。例如,要创建一个使用 number 算法进行清理的快照,请执行
# snapper -c config create -c number
有关 timeline 快照的工作原理,请参阅 #自动时间线快照,有关 pre 和 post 的工作原理,请参阅 #预/后快照。
预/后快照
另一类快照——*预/后*快照——旨在成对创建,一个在重大更改(例如系统更新)之前,一个在之后。
如果重大更改可以通过单个命令调用(或可以调用),则可以使用 snapper create --command 来调用该命令并自动创建 *预/后* 快照。
# snapper -c config create --command cmd
--command 选项更好的输出重定向。或者,也可以手动创建 *预/后* 快照。
首先创建一个 *预* 快照
# snapper -c config create -t pre -p
记下新快照的编号(创建 *后* 快照需要它)。
现在执行将修改文件系统的操作(*例如*,安装新程序、升级等)。
最后,创建 *后* 快照,将 N 替换为 *预* 快照的编号。
# snapper -c config create -t post --pre-number N
另请参阅 #将 pacman 事务包装在快照中。
启动时快照
要让 snapper 对 root 配置拍摄快照,请启用 snapper-boot.timer。(这些快照是 *单个* 类型。)
管理快照
列出配置
要列出已创建的所有 配置,请执行
# snapper list-configs
列出快照
要列出给定配置 config 拍摄的快照,请执行
# snapper -c config list
恢复快照
在恢复快照时,一个文件可能会被保留,原因可能是它未包含在快照中(例如,它位于其他子卷上),或者是因为过滤器配置排除了该文件。
过滤配置
某些文件保留了系统的状态信息,例如 /etc/mtab。这些文件永远不应被恢复。Arch Linux 中的默认配置确保了这一点。为了方便用户,snapper 允许忽略这些文件。/etc/snapper/filters/*.txt 和 /usr/share/snapper/filters/*.txt 中的每一行都指定了一个模式。当 snapper 计算两个快照之间的差异时,它会忽略匹配任何这些模式的文件和目录。请注意,过滤器不会将文件或目录排除在快照之外。为此,请使用子卷或挂载点。
另请参阅 SLES 12 SP5 文档中的 从快照中排除的目录。
使用默认布局恢复
如果您使用 snapper 的默认布局,每个快照都是子卷目录 .snapshots 中的一个子子卷,例如 @home。
要使用 snapper 的快照恢复 /home,首先启动到 live Arch Linux USB/CD。
使用 UUID 将 btrfs 根卷挂载到 /mnt
# mount -t btrfs -o subvol=/ /dev/disk/by-uuid/UUID_of_root_volume /mnt # cd /mnt
如果 snapper 服务在一个运行的系统上运行,请停止它。检查是否有任何 snapper-unit.timers 正在运行,然后停止它们。
将损坏/旧的子卷移到一边,例如将 @home 移到 @home-backup
# mv @home @home-backup
查找要恢复的快照编号(每个快照有一行,因此您可以轻松匹配快照的编号和日期)。
# grep -r '<date>' /mnt/@home-backup/.snapshots/*/info.xml
... /mnt/@home-backup/.snapshots/number/info.xml: <date>2021-07-26 22:00:00</date> ...
info.xml 中记录的日期和时间的时区是 UTC,因此必须考虑与本地时间的时差。记住 number。
从要恢复的快照编号 number 创建一个新的快照 @home。
# btrfs subvolume snapshot @home-backup/.snapshots/number/snapshot @home
将 .snapshots 目录恢复到健康的子卷,例如 @home
# mv @home-backup/.snapshots @home/
如果 /home 的挂载选项在 fstab 中使用了 subvolid 而不是 /path/to/subvolume,请在 /mnt/@/etc/fstab 文件中(假设 @ 是挂载为 / 的子卷)将 subvolid 更改为新的 subvolid,该新的 subvolid 可以通过 btrfs subvolume list /mnt | grep @home$ 找到。
重启。
检查您的系统是否按预期工作,如果需要,删除旧的/损坏的快照(例如 @home-backup)。您应该检查它是否包含您可以取回的有用数据。
删除快照
要删除快照编号 N,请执行
# snapper -c config delete N
一次可以删除多个快照。例如,要删除根配置的快照 65 和 70,请执行
# snapper -c root delete 65 70
要删除一系列快照,在本例中是根配置的快照 65 到 70,请执行
# snapper -c root delete 65-70
要立即释放快照占用的空间,请使用 --sync。
# snapper -c root delete --sync 65
要删除所有快照,.snapshots 子卷和配置的 snapper 配置文件
# snapper -c config delete-config
非 root 用户的访问权限
每个配置都是以 root 用户创建的,默认情况下,只有 root 用户可以查看和访问它。
要允许特定用户列出给定配置的快照,只需更改 /etc/snapper/configs/config 文件中的 ALLOW_USERS 值。您现在应该可以作为普通用户运行 snapper -c config list。
最终,您可能希望能够使用普通用户浏览 .snapshots 目录,但该目录的所有者仍必须是 root。因此,您应该更改组所有权,使其属于包含您感兴趣的用户的组,例如 users。
# chmod a+rx .snapshots # chown :users .snapshots
技巧与提示
将 Snapper 用作普通用户
要允许普通用户使用 snapper(例如,用于 /home 快照),您可以使用 SYNC_ACL 选项。
# snapper -c home_user create-config /home/user # snapper -c home_user set-config "ALLOW_USERS=user" SYNC_ACL="yes"
另请参阅 [4]
将 pacman 事务包装在快照中
有几个软件包用于在 pacman 事务上自动创建快照
- snap-pac — 使 pacman 自动使用 snapper 创建预/后快照,类似于 openSUSE 的 YaST。使用 pacman hooks。
- grub-btrfs — 包括一个守护进程 (grub-btrfsd),可以通过 systemctl 启用它来查找新快照并自动将其包含在 GRUB 菜单中。要使该守护进程正常工作,您需要安装可选依赖项 inotify-tools。
- snap-pac-grub — 在 snap-pac 创建快照后,还会更新 GRUB 条目以支持 grub-btrfs。也使用 pacman hooks。
- snp — 将任何 shell 命令包装在 snapper 预-后快照中(例如
snp pacman -Syu),比 snapper 的原生--command选项提供更好的输出(参见 #预/后快照)。
- https://gitlab.com/Zesko/limine-snapper-sync || limine-snapper-syncAUR (有关详细信息,请参阅 Limine#Snapper snapshot integration for Btrfs。)
启动到只读快照
依赖于 grub-btrfs 或 snap-pac-grubAUR 或 limine-snapper-syncAUR 的用户应注意,默认情况下,Snapper 的快照是只读的,并且启动到只读快照存在一些固有的困难。许多服务,例如桌面管理器,都需要一个可写目录 /var,并且在从只读快照启动时会失败。
为了解决这个问题,您可以将快照设为可写,或者使用开发者批准的方法,通过 overlay filesystem 引导快照,使快照的行为类似于 Live CD 环境。
使用 overlayfs 引导快照
- 确保您的系统已安装 grub-btrfs。
- 将
grub-btrfs-overlayfs添加到/etc/mkinitcpio.conf中的HOOKS数组末尾。例如HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block filesystems fsck grub-btrfs-overlayfs)
注意 因为 grub-btrfs-overlayfs 只提供一个 运行时钩子 而没有 systemd 单元,所以它**不**兼容基于 systemd 的 initramfs。确保您使用基于 Busybox 的 initramfs。有关更多详细信息,请参阅 此 GitHub issue。 - 重新生成 initramfs.
进一步阅读
- grub-btrfs README(包含使用 dracut 而不是 mkinitcpio 的说明)
- GitHub 上的讨论
在 pacman 事务中备份非 Btrfs 引导分区
如果您的 /boot 分区位于非 Btrfs 文件系统上(例如,ESP),您将无法使用 snapper 进行备份。请参阅 System backup#Snapshots and /boot partition,以通过 hook 在内核更新时自动将引导分区复制到您的 Btrfs 根分区。这也可以与 snap-pac 很好地配合使用。
增量备份到外部驱动器
一些工具可以使用 snapper 自动化备份。请参阅 Btrfs#Incremental backup to external drive。
建议的文件系统布局
以下是轻松将挂载在根目录的子卷 @ 恢复到先前快照的建议文件系统布局
| 子卷 | 挂载点 |
|---|---|
| @ | / |
| @home | /home |
| @snapshots | /.snapshots |
| @var_log | /var/log |
subvolid=5 | ├── @ -| | contained directories: | ├── /usr | ├── /bin | ├── /.snapshots | ├── ... | ├── @home ├── @snapshots ├── @var_log └── @...
子卷 @... 被挂载到任何其他应该有自己子卷的目录。
如果您将系统恢复到 @ 的先前快照,这些其他子卷将不受影响。例如,这允许您将 @ 恢复到先前快照,同时保持 /home 不变,因为 /home 是挂载的一个子卷。
此布局允许 snapper 工具对 / 拍摄常规快照,同时在系统无法启动时,可以轻松地从 Arch Live CD 恢复 /。
在此场景下,初始设置后,snapper 无需更改即可按预期工作。
- 考虑为不希望包含在
@子卷的快照和回滚中的数据目录创建子卷,例如/var/cache、/var/spool、/var/tmp、/var/lib/machines(systemd-nspawn)、/var/lib/docker(Docker)、/var/lib/postgres(PostgreSQL)以及/var/lib/下的其他数据目录。是否遵循*扁平*布局或创建嵌套子卷由您决定。另一方面,/var/lib/pacman中的 pacman 数据库必须保留在根子卷(@)上。 - 您可以对
@home和任何其他子卷运行 Snapper,以便为数据提供单独的快照和回滚功能。
Snapper 和挂载点的配置
假定子卷 @ 被挂载在根目录 /。还假定 /.snapshots*未*被挂载且*不*存在为文件夹,这可以通过以下命令确保:
# umount /.snapshots # rm -r /.snapshots
然后为 /创建新配置。Snapper create-config 会自动创建一个名为 .snapshots 的子卷,其父卷是根子卷 @,这对于建议的文件系统布局是不需要的,可以删除。
# btrfs subvolume delete /.snapshots
删除子卷后,重新创建目录 /.snapshots。
# mkdir /.snapshots
现在将 @SNAPSHOTS 挂载到 /.SNAPSHOTS。例如,对于位于 /dev/sda1 的文件系统
# mount -o subvol=@snapshots /dev/sda1 /.snapshots
为了使此挂载永久生效,请在您的 fstab 中添加一个条目。
或者,如果您有一个现有的 fstab 条目,则重新挂载快照子卷
# mount -a
为文件夹 750 设置权限。
这将使 snapper 创建的所有快照都存储在 @ 子卷之外,以便随时轻松替换 @ 而不会丢失 snapper 快照。
将 / 恢复到其之前的快照
要使用 snapper 的快照恢复 /,首先启动到 live Arch Linux USB/CD。
挂载 顶层子卷(subvolid=5)。也就是说,省略任何 subvolid 或 subvol 挂载标志。
查找要恢复的快照编号
# grep -r '<date>' /mnt/@snapshots/*/info.xml
输出应如下所示,每个快照有一行,因此您可以轻松匹配快照的编号和日期。
/mnt/@snapshots/number/info.xml: <date>2021-07-26 22:00:00</date>
info.xml 中记录的日期和时间的时区是 UTC,因此必须考虑与本地时间的时差。记住 number。
现在,将 @ 移动到另一个位置(*例如* /@.broken)以保存当前系统的副本。或者,直接使用 btrfs subvolume delete /mnt/@ 删除 @。
创建要恢复的只读快照的读写快照
# btrfs subvolume snapshot /mnt/@snapshots/number/snapshot /mnt/@
其中 number 是您希望恢复的 snapper 快照的编号。
如果 / 的挂载选项在 fstab 中使用了 subvolid 而不是 /path/to/subvolume,请在 /mnt/@/etc/fstab 文件中将 subvolid 更改为新的 subvolid,该新的 subvolid 可以通过 btrfs subvolume list /mnt | grep @$ 找到。另外,请更改引导加载程序配置,例如 refind_linux.conf,如果它包含 subvolid。
最后,卸载顶层子卷(ID=5),然后将 @ 挂载到 /mnt,并将您的 ESP 或引导分区挂载到相应的挂载点。chroot 到您恢复的快照中,以便重新生成您的 initramfs 映像。
您的 / 现在已恢复到之前的快照。然后只需重新启动。
/etc/snapper-rollback.conf 以匹配您的系统。恢复其他子卷到其之前的快照
参见 #恢复快照。
从快照中删除文件
如果您想从过去的快照中删除特定文件或文件夹而不删除快照本身,snappersAUR 是一个脚本,它为 Snapper 增加了此功能。此脚本还可以用于以 Snapper 目前不支持的许多其他方式操作过去的快照。
如果您想在不使用额外脚本的情况下删除文件,您只需 将您的快照子卷设为读写,您可以通过以下方式做到:
# btrfs property set /path/to/.snapshots/<snapshot_num>/snapshot ro false
验证 ro=false
# btrfs property get /path/to/.snapshots/<snapshot_num>/snapshot ro=false
您现在可以像平常一样修改 /path/to/.snapshots/<snapshot_num>/snapshot 中的文件。您可以使用 shell 循环批量处理您的快照。
防止性能下降
在繁忙的文件系统(如 /)上,在较长的时间范围内保留大量快照,在这些文件系统上会发生许多系统更新,可能会导致严重的性能下降。您可以通过以下方式防止这种情况:
updatedb
默认情况下,updatedb(参见 locate)也会索引 snapper 创建的 .snapshots 目录,如果您有很多快照,这可能会导致严重的性能下降和过高的内存使用。您可以通过编辑以下内容来防止 updatedb 索引该目录:
/etc/updatedb.conf
PRUNENAMES = ".snapshots"
禁用配额组
有报告称配额组会导致显著的性能下降,例如,如果 snapper ls 需要几分钟才能返回结果,这可能是原因。参见 [5]。
使用以下命令确定配额组是否已启用
# btrfs qgroup show /
配额组随后可以使用以下方式禁用:
# btrfs quota disable /
计算快照数量
如果禁用配额组未能解决性能下降问题,计算快照数量可能有所帮助,可以通过以下方式完成:
# btrfs subvolume list -s / | wc -l
为用户数据和日志创建子卷
建议将包含用户数据(例如电子邮件或日志)的目录存储在它们自己的子卷中,而不是根子卷 / 中。这样,如果恢复 / 的快照,用户数据和日志也不会恢复到之前的状态。可以为用户数据维护单独的时间线快照。不建议为 /var/log 中的日志创建快照。这样可以更容易地进行故障排除。
也可以使用 #过滤配置 在恢复过程中跳过目录。有关跳过某些路径的示例和原因,请参阅 SLES 文档。
基于磁盘使用量的清理
故障排除
Snapper 日志
Snapper 将所有活动写入 /var/log/snapper.log - 如果您认为有问题,请首先检查此文件。
如果您在小时/每日/每周快照方面遇到问题,到目前为止最常见的原因是 cronie 服务(或您使用的任何 cron 守护进程)未运行。
IO 错误
如果您在尝试创建快照时遇到“IO 错误”,请确保您尝试快照的子卷相关的 .snapshots 目录本身就是一个子卷。
另一种可能的原因是 .snapshots 目录的所有者不是 root(您会在 /var/log/snapper.log 中找到 Btrfs.cc(openInfosDir):219 - .snapshots must have owner root)。
孤立的快照导致磁盘空间浪费
快照可能会“丢失”,即它们仍然存在于磁盘上但未被 snapper 跟踪。这可能导致大量浪费、未计入的磁盘空间。要对此进行检查,请比较以下输出:
# snapper -c <config> list
更改为
# btrfs subvolume list -o <parent subvolume>/.snapshots
第二个列表中任何不在第一个列表中的子卷都是孤立的,可以手动 删除。