Snapper
Snapper 是 openSUSE 的 Arvin Schnell 创建的工具,用于帮助管理 Btrfs 子卷和精简配置的 LVM 卷的快照。它可以创建和比较快照,在快照之间恢复,并支持自动快照时间线。
安装
安装 snapper 软件包。开发版本 snapper-gitAUR 也可用。
此外,GUI 可通过 snapper-gui-gitAUR、 btrfs-assistantAUR 和 snapper-toolsAUR 获得。
创建新配置
在为 Btrfs 子卷创建 snapper 配置之前,子卷必须已经存在。如果不存在,您应该在生成 snapper 配置之前创建它。
要为 /path/to/subvolume
处的 Btrfs 子卷创建名为 config
的新 snapper 配置,请运行
# snapper -c config create-config /path/to/subvolume
这将
- 基于
/usr/share/snapper/config-templates
中的默认模板,在/etc/snapper/configs/config
创建一个配置文件。 - 在
/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
命令将失败 [1]。要将 @.snapshots
子卷用于 Snapper 备份,请执行以下操作- 卸载
@.snapshots
子卷并删除现有的挂载点。 - 创建 Snapper 配置。
- 删除 Snapper 创建的子卷。
- 重新创建
/.snapshots
挂载点并重新挂载@.snapshots
子卷。
此时,配置已激活。如果您的 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 拍摄的快照类型为single,与其他快照没有特殊关系。
要手动拍摄子卷的快照,请执行
# snapper -c config create --description desc
上述命令不使用任何清理算法,因此快照将永久存储,直到删除。
要设置清理算法,请在 create
之后使用 -c
标志,并选择 number
、timeline
、pre
或 post
。number
设置 snapper 定期删除已超过配置文件中设置数量的快照。例如,要创建一个使用 number
算法进行清理的快照,请执行
# snapper -c config create -c number
有关 timeline
快照的工作原理,请参阅 #自动时间线快照,有关 pre
和 post
的工作原理,请参阅 #前/后 快照。
前/后 快照
另一种类型的快照 - pre/post 快照 - 旨在成对创建,一个在重大更改之前,一个在重大更改之后(例如系统更新)。
如果重大更改是/可以通过单个命令调用,则可以使用 snapper create --command
来调用该命令并自动创建 pre/post 快照
# snapper -c config create --command cmd
--command
选项提供更好的输出重定向。或者,pre/post 快照可以手动创建。
首先创建一个 pre 快照
# snapper -c config create -t pre -p
记下新快照的编号(创建 post 快照时需要它)。
现在执行将修改文件系统的操作(*例如*,安装新程序、升级等)。
最后,创建 post 快照,将 N
替换为 pre 快照的编号
# snapper -c config create -t post --pre-number N
另请参阅 #在快照中包装 pacman 事务。
启动时快照
要让 snapper 拍摄 root
配置的快照,请启用 snapper-boot.timer
。(这些快照的类型为 single。)
管理快照
列出配置
要列出已创建的所有配置,请执行
# snapper list-configs
列出快照
要列出为给定配置 config 拍摄的快照,请执行
# snapper -c config list
恢复快照
当恢复快照时,文件可能会保持原样,原因可能是该文件未包含在快照中(例如,它位于另一个子卷上),或者因为过滤器配置排除了该文件。
过滤器配置
某些文件保留系统的状态信息,例如 /etc/mtab
。永远不应还原此类文件。arch linux 中的默认配置确保了这一点。为了帮助用户,snapper 允许用户忽略这些文件。所有文件 /etc/snapper/filters/*.txt
和 /usr/share/snapper/filters/*.txt
中的每一行都指定一个模式。当 snapper 计算两个快照之间的差异时,它会忽略与任何这些模式匹配的所有文件和目录。请注意,过滤器不会将文件或目录排除在快照之外。为此,请使用子卷或挂载点。
另请参阅 SLES 文档中的从快照中排除的目录[死链接 2024-03-03 ⓘ]。
使用默认布局恢复
如果您正在使用 snapper 的默认布局,则每个快照都是子卷 .snapshots
目录中的子子卷,例如 @home
。
要使用 snapper 的快照之一恢复 /home
,请首先启动到 Arch Linux Live 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/
如果在 fstab 中为 /home
挂载条目选项使用了 subvolid,而不是 /path/to/subvolume
,请在 /mnt/@/etc/fstab
文件中将 subvolid 更改为可以使用 btrfs subvolume list /mnt | grep @home$
找到的新 subvolid。(假设 @
是系统中挂载为 /
的子卷)。
重启。
检查您的系统是否按预期工作,如果需要,删除旧的/损坏的快照(例如 @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
技巧和窍门
在快照中包装 pacman 事务
有一些软件包用于在 pacman 事务时自动创建快照
- snap-pac — 使 pacman 自动使用 snapper 创建 pre/post 快照,如 openSUSE 的 YaST。使用 pacman 钩子。
- grub-btrfs — 包括一个守护程序 (grub-btrfsd),可以通过 systemctl 启用该守护程序来查找新快照并自动将其包含在 GRUB 菜单中。
- snap-pac-grub — 此外,在 snap-pac 制作快照后,更新 grub-btrfs 的 GRUB 条目。也使用 pacman 钩子。
- snp — 将任何 shell 命令包装在 snapper pre-post 快照中(例如
snp pacman -Syu
),比 snapper 的原生--command
选项具有更好的输出(请参阅 #前/后 快照)。
- https://gitlab.com/Zesko/limine-snapper-sync || limine-snapper-syncAUR (有关详细信息,请参阅 Limine#Snapper 快照集成(用于 Btrfs)。)
启动到只读快照
依赖 grub-btrfs 或 snap-pac-grubAUR 或 limine-snapper-syncAUR 的用户应注意,默认情况下,Snapper 的快照是只读的,并且启动到只读快照存在一些固有的困难。许多服务(例如桌面管理器)都需要可写的 /var
目录,并且从只读快照启动时将无法启动。
为了解决这个问题,您可以使快照可写,或者使用开发人员批准的 overlayfs 启动快照的方法,使快照的行为类似于 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 问题。 - 重新生成 initramfs.
进一步阅读
- grub-btrfs README(包括为使用 dracut 而不是 mkinitcpio 的用户提供的说明)
- Github 上的讨论
在 pacman 事务中备份非 Btrfs 启动分区
如果您的 /boot
分区位于非 Btrfs 文件系统(例如 ESP)上,则您无法使用它进行 snapper 备份。请参阅 系统备份#快照和 /boot 分区,以在内核更新时使用钩子自动将启动分区复制到 Btrfs 根目录。这也与 snap-pac 配合良好。
增量备份到外部驱动器
一些工具可以使用 snapper 来自动化备份。请参阅 Btrfs#增量备份到外部驱动器。
建议的文件系统布局
这是一个建议的文件系统布局,用于轻松地将挂载在根目录的子卷 @
恢复到之前的快照
子卷 | 挂载点 |
---|---|
@ | / |
@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 的快照之一恢复 /
,请首先启动到 Arch Linux Live 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/@
删除 @
。
创建 snapper 拍摄的只读快照的读写快照
# btrfs subvolume snapshot /mnt/@snapshots/number/snapshot /mnt/@
其中 number
是您要恢复的 snapper 快照的编号。
如果在 fstab 中为 /
挂载条目选项使用了 subvolid,而不是 /path/to/subvolume
,请在 /mnt/@/etc/fstab
文件中将 subvolid 更改为可以使用 btrfs subvolume list /mnt | grep @$
找到的新 subvolid。如果引导加载程序配置(例如 refind_linux.conf
)包含 subvolid,也请更改它。
最后,卸载顶层子卷 (ID=5),然后挂载 @
到 /mnt
,并将您的 ESP 或启动分区挂载到适当的挂载点。切换根目录到您恢复的快照,以便重新生成您的 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 循环来批量处理快照。
防止速度减慢
在繁忙的文件系统(如 /
)上为较长时间范围保留大量快照可能会导致严重的速度减慢,因为随着时间的推移会发生许多系统更新。您可以通过以下方式防止这种情况:
- 创建不值得快照的项目的子卷,例如
/var/cache/pacman/pkg
、/var/abs
、/var/tmp
和/srv
。 - 当使用 #自动时间线快照 时,编辑每小时/每天/每月/每年的快照的默认设置。
updatedb
默认情况下,updatedb
(参见 locate)也会索引 snapper 创建的 .snapshots
目录,如果您有很多快照,这可能会导致严重的速度减慢和过多的内存使用。您可以通过编辑以下内容来阻止 updatedb
索引它:
/etc/updatedb.conf
PRUNENAMES = ".snapshots"
禁用配额组
有报告称,配额组会导致明显的减速,例如,如果 snapper ls
需要几分钟才能返回结果,则可能是由配额组引起的。请参阅 [3]。
要确定是否启用了配额组,请使用以下命令
# 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
第二个列表中存在但第一个列表中不存在的任何子卷都是孤立的,可以手动 删除。