跳转至内容

Snapper

来自 ArchWiki

Snapper 是由 openSUSE 的 Arvin Schnell 创建的一个工具,用于管理 Btrfs 子卷、精简配置的 LVM 卷,以及(实验性地)Bcachefs 子卷的快照。它可以创建和比较快照,在快照之间回滚,并支持自动快照时间线。

安装

安装 snapper 包。

此外,还有可用的 GUI,例如 btrfs-assistantsnapper-gui-gitAURsnapper-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 /
注意 如果您使用 archinstall 版本早于 3.0.5 的建议 Btrfs 分区布局 [1] 安装 Arch,那么 @.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 来定期清理旧快照。

注意 如果您有 cron 守护进程并且还启用了 systemd 单元,这可能会导致创建重复的快照。如果您希望在使用 systemd 单元的同时禁用 cron 集成,一种可能的解决方案是不通过 pacman 的 NoExtract 配置选项来安装 snapper 包的 cron 文件。请参阅 [3]

设置快照限制

默认设置将保留 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/Timerssystemd#Drop-in 文件

手动快照

单个快照

默认情况下,snapper 创建的是 *单个* 类型的快照,与其他快照没有特殊关系。

要手动拍摄子卷的快照,请执行

# snapper -c config create --description desc

上面的命令不使用任何清理算法,因此快照将被永久存储,直到删除为止。

要设置清理算法,请在 create 之后使用 -c 标志,并选择 numbertimelineprepostnumber 设置 snapper 定期删除已超过配置文件中设定的数量的快照。例如,要创建一个使用 number 算法进行清理的快照,请执行

# snapper -c config create -c number

有关 timeline 快照的工作原理,请参阅 #自动时间线快照,有关 prepost 的工作原理,请参阅 #预/后快照

预/后快照

另一类快照——*预/后*快照——旨在成对创建,一个在重大更改(例如系统更新)之前,一个在之后。

如果重大更改可以通过单个命令调用(或可以调用),则可以使用 snapper create --command 来调用该命令并自动创建 *预/后* 快照。

# snapper -c config create --command cmd
提示 要将任何 shell 命令包装在 *预/后* 快照中,您还可以考虑使用 snpAUR shell 脚本,它提供了比 snapper 的原生 --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 是指向 /proc/self/mounts 的符号链接,因此恢复它对系统没有影响。(在 Talk:Snapper 中讨论)

某些文件保留了系统的状态信息,例如 /etc/mtab。这些文件永远不应被恢复。Arch Linux 中的默认配置确保了这一点。为了方便用户,snapper 允许忽略这些文件。/etc/snapper/filters/*.txt/usr/share/snapper/filters/*.txt 中的每一行都指定了一个模式。当 snapper 计算两个快照之间的差异时,它会忽略匹配任何这些模式的文件和目录。请注意,过滤器不会将文件或目录排除在快照之外。为此,请使用子卷或挂载点。

本文或本章节的准确性存在争议。

原因: SLES 文档中的列表与 Arch Linux 有何关系?(在 Talk:Snapper 中讨论)

另请参阅 SLES 12 SP5 文档中的 从快照中排除的目录

使用默认布局恢复

本文或本章节的准确性存在争议。

原因: 什么是“默认布局”?替代方案是什么?(在 Talk:Snapper 中讨论)

如果您使用 snapper 的默认布局,每个快照都是子卷目录 .snapshots 中的一个子子卷,例如 @home

本文或本章节的准确性存在争议。

原因: 未用于 / 的子卷可以从系统本身恢复。只需以 root 登录,确保子卷未被使用,然后将其卸载。(在 Talk:Snapper 中讨论)

要使用 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

本文或本章节的准确性存在争议。

原因: 这是为 live Arch Linux USB/CD 编写的,其中 snapper 服务无法运行。(在 Talk:Snapper 中讨论)

如果 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 选项。

注意 确保访问控制列表(ACL)已启用
# snapper -c home_user create-config /home/user
# snapper -c home_user set-config "ALLOW_USERS=user" SYNC_ACL="yes"

另请参阅 [4]

将 pacman 事务包装在快照中

有几个软件包用于在 pacman 事务上自动创建快照

https://github.com/wesbarnett/snap-pac || snap-pac
  • grub-btrfs — 包括一个守护进程 (grub-btrfsd),可以通过 systemctl 启用它来查找新快照并自动将其包含在 GRUB 菜单中。要使该守护进程正常工作,您需要安装可选依赖项 inotify-tools
https://github.com/Antynea/grub-btrfs || grub-btrfs
https://github.com/maximbaz/snap-pac-grub || snap-pac-grubAUR
  • refind-btrfs — 在 snap-pac 创建快照后,将条目添加到 rEFInd
https://github.com/Venom1991/refind-btrfs || refind-btrfsAUR
  • snp — 将任何 shell 命令包装在 snapper 预-后快照中(例如 snp pacman -Syu),比 snapper 的原生 --command 选项提供更好的输出(参见 #预/后快照)。
https://gist.github.com/erikw/5229436 || snpAUR
https://gitlab.com/Zesko/limine-snapper-sync || limine-snapper-syncAUR (有关详细信息,请参阅 Limine#Snapper snapshot integration for Btrfs。)

启动到只读快照

依赖于 grub-btrfssnap-pac-grubAURlimine-snapper-syncAUR 的用户应注意,默认情况下,Snapper 的快照是只读的,并且启动到只读快照存在一些固有的困难。许多服务,例如桌面管理器,都需要一个可写目录 /var,并且在从只读快照启动时会失败。

为了解决这个问题,您可以将快照设为可写,或者使用开发者批准的方法,通过 overlay filesystem 引导快照,使快照的行为类似于 Live CD 环境。

注意 您在此快照中所做的任何文件更改都不会被保存,因为文件系统仅存在于 RAM 中。

使用 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.

进一步阅读

提示 或者,您可以使用 Limine 引导加载程序启动到快照。Snapper 和 Limine 之间的集成由 limine-snapper-syncAUR 提供,有关详细信息,请参阅 Limine#Snapper snapshot integration for Btrfs

在 pacman 事务中备份非 Btrfs 引导分区

如果您的 /boot 分区位于非 Btrfs 文件系统上(例如,ESP),您将无法使用 snapper 进行备份。请参阅 System backup#Snapshots and /boot partition,以通过 hook 在内核更新时自动将引导分区复制到您的 Btrfs 根分区。这也可以与 snap-pac 很好地配合使用。

增量备份到外部驱动器

一些工具可以使用 snapper 自动化备份。请参阅 Btrfs#Incremental backup to external drive

建议的文件系统布局

注意 以下布局*不*打算与 snapper rollback 一起使用,而是旨在缓解 #将 / 恢复到其之前的快照 的固有问题。请参阅此 论坛帖子

以下是轻松将挂载在根目录的子卷 @ 恢复到先前快照的建议文件系统布局

文件系统布局
子卷 挂载点
@ /
@home /home
@snapshots /.snapshots
@var_log /var/log
subvolid=5
  |
  ├── @ -|
  |     contained directories:
  |       ├── /usr
  |       ├── /bin
  |       ├── /.snapshots
  |       ├── ...
  |
  ├── @home
  ├── @snapshots
  ├── @var_log
  └── @...

子卷 @... 被挂载到任何其他应该有自己子卷的目录。

  • 拍摄 @(挂载在根目录 /)的快照时,其他子卷不包含在快照中。即使子卷嵌套在 @ 下方,@ 的快照也不会包含它。为 @ 之外的其他子卷创建 snapper 配置,如果您希望保留其快照。
  • 由于 Btrfs 的限制,被快照化的卷不能包含交换文件。要么将交换文件放在另一个子卷上,要么创建一个交换分区

如果您将系统恢复到 @ 的先前快照,这些其他子卷将不受影响。例如,这允许您将 @ 恢复到先前快照,同时保持 /home 不变,因为 /home 是挂载的一个子卷。

此布局允许 snapper 工具对 / 拍摄常规快照,同时在系统无法启动时,可以轻松地从 Arch Live CD 恢复 /

在此场景下,初始设置后,snapper 无需更改即可按预期工作。

提示
  • 考虑为不希望包含在 @ 子卷的快照和回滚中的数据目录创建子卷,例如 /var/cache/var/spool/var/tmp/var/lib/machinessystemd-nspawn)、/var/lib/dockerDocker)、/var/lib/postgresPostgreSQL)以及 /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)。也就是说,省略任何 subvolidsubvol 挂载标志。

查找要恢复的快照编号

# 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 映像

您的 / 现在已恢复到之前的快照。然后只需重新启动。

提示 您也可以使用为该布局设计的自动回滚工具:snapper-rollbackAUR。编辑配置文件 /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 需要几分钟才能返回结果,这可能是原因。参见 [5]

使用以下命令确定配额组是否已启用

# btrfs qgroup show /

配额组随后可以使用以下方式禁用:

# btrfs quota disable /

计算快照数量

如果禁用配额组未能解决性能下降问题,计算快照数量可能有所帮助,可以通过以下方式完成:

# btrfs subvolume list -s / | wc -l

为用户数据和日志创建子卷

建议将包含用户数据(例如电子邮件或日志)的目录存储在它们自己的子卷中,而不是根子卷 / 中。这样,如果恢复 / 的快照,用户数据和日志也不会恢复到之前的状态。可以为用户数据维护单独的时间线快照。不建议为 /var/log 中的日志创建快照。这样可以更容易地进行故障排除。

也可以使用 #过滤配置 在恢复过程中跳过目录。有关跳过某些路径的示例和原因,请参阅 SLES 文档

基于磁盘使用量的清理

本文章或章节需要扩充。

原因:有关想法,请参阅 [6]。(在 Talk:Snapper 中讨论)

故障排除

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 

第二个列表中任何不在第一个列表中的子卷都是孤立的,可以手动 删除

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.