跳转到内容
来自 Arch Linux 中文维基

Snapper 是一个由 openSUSE 的 Arvin Schnell 开发的工具,用于管理 Btrfs 子卷和 LVM 精简配置(thin-provisioned)卷。它可以创建和比较快照,在快照间回滚,并支持自动按时间序列创建快照。

安装

安装 snapper 包。或者安装开发版本 snapper-gitAUR

此外,还可以安装 GUI 前端 snapper-gui-gitAURbtrfs-assistantAURsnapper-toolsAUR

建立一个新的配置

在为 btrfs 子卷建立一个 snapper 配置前,这个子卷必须已经存在。否则,你应该在建立 snapper 配置前创建它。

要为位置为 /path/to/subvolume 的 btrfs 子卷创建一个新的 snapper 配置文件,并命名为 config

# snapper -c config create-config /path/to/subvolume

这将会:

  • 根据 /usr/share/snapper/config-templates/default 处的默认配置模板创建一个配置文件 /etc/snapper/configs/config
  • /path/to/subvolume/.snapshots 处创建一个子卷,用于存储未来该配置文件产生的子卷。子卷的路径将会是 /path/to/subvolume/.snapshots/#/snapshot# 是子卷序号。
  • config 加入到 /etc/conf.d/snapperSNAPPER_CONFIGS 中。

例如,要为挂载在 / 的子卷创建一个配置文件:

# snapper -c root create-config /
注意:如果你正在使用 archinstall 推荐的 btrfs 分区布局,则 @.snapshots 子卷已经被挂载到 /.snapshots,这会导致 snapper create-config 无法正常创建配置 [1]。要让 Snapper 使用 @.snapshots 来创建备份,需要进行如下操作:
  • 卸载 @.snapshots 子卷并删除已存在的挂载点。
  • 创建 Snapper 配置。
  • 删除 Snapper 创建的子卷。
  • 重新创建 /.snapshots 挂载点,重新挂载 @.snapshots 子卷。

此时,配置文件已经激活。如果你的 cron 守护进程已经运行, snapper 将会使用 #自动按时创建快照。否则,你需要使用 systemd 单元文件和定时器。参阅 #启用/停用

参阅 snapper-configs(5)

创建快照

自动按时创建快照

一个快照时间线(timeline)由可配置数目的每小时/日/月/年快照组成。当自动按时创建启用时,默认每小时创建一个快照。每天由时间线清理算法清理多余快照。详情请参照 snapper-configs(5) 中的 TIMELINE_* 变量。

启用/停用

如果你拥有一个 cron 守护进程,该特性应该已经自动启用。要停用,编辑你想禁用该特性的子卷对应配置文件为:

TIMELINE_CREATE="no"

如果你没有 cron 守护进程,你可以使用提供的 systemd 单元文件。启动启用 snapper-timeline.timer 来启用自动按时创建快照。另外,启用启动 snapper-cleanup.timer 来定期清理老旧快照。

注意:如果你有一个 cron 守护进程并同时启用了 systemd 单元,这可能会导致重复创建快照。如果你希望使用 systemd 单元并禁用 cron 集成,一中可行的方法是使用 pacman 的 NoExtract 配置选项。参见[2]

设置快照限制

默认配置将保留 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/定时器Systemd#附加配置片段

手动创建快照

Single 快照

默认情况下 snapper 创建 single 类型的快照,它们与其他快照没有特别关系。

要为一个子卷创建快照:

 # snapper -c config create --description desc

以上命令没有对应的清理算法,因此该快照将会一直存储直到 删除 它。

要设置一个清理算法,在 create 后使用 -c 选项,并在 numbertimelineprepost 中选择一个参数。 number 使 snapper 定期清理超出配置文件中设置的数量限制的快照。例如,要创建一个使用 number 清理算法的快照:

 # snapper -c config create -c number

参阅 #自动按时创建快照 查看 timeline 是如何工作的。参阅 #pre/post 快照 查看 pre post 如何工作。

pre/post 快照

另一种快照类型是 pre/post 快照。两个快照会在进行重大更改时先后成对创建(例如进行系统更新时)。


如果这种重大更改是/可被单个命令调用,那么 snapper create --command 可以在调用这个命令的同时创建 pre/post 快照。


# snapper -c config create --command cmd
提示:要在创建 pre/post 快照时执行任何 shell 命令,可以考虑使用 snpAUR 脚本。这个脚本相比 Snapper 自身的 --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 is a symlink to /proc/self/mounts, so reverting it has no effect on the system.(在 Talk:Snapper 中讨论)


部分文件保存着系统的状态信息,例如 /etc/mtab。这些文件不应该被还原。Arch Linux 提供的 Snapper 的默认配置已经排除了这些文件。Snapper 支持按照用户排除某些文件或文件夹。/etc/snapper/filters/*.txt/usr/share/snapper/filters/*.txt 中的每行指定了要排除的项目。当 Snapper 计算快照之间的差别时,会排除这些文件。注意,这些文件仍会包含在快照中,如果不想让这些文件包含在快照中,使用单独的子卷或者挂载点。

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

原因: How is the list from SLES documentation relevant for Arch Linux?(在 Talk:Snapper 中讨论)


参见 SUSE 的文档Directories That Are Excluded from Snapshots[失效链接 2024-03-03 ⓘ]

还原快照

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

原因: What is the "default layout"? What is the alternative?(在 Talk:Snapper 中讨论)


如果你使用 Snapper 的默认布局,每个快照是在所指定子卷下的 .snapshots 目录的下层子卷,例如 @home 的快照位于 @home/.snapshots下。

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

原因: Subvolumes that are not used for / can be restored from the system itself. Just log in as root, make sure that the subvolume is not used, and unmount it.(在 Talk:Snapper 中讨论)


例如要将某个快照恢复到 home,首先启动到 Arch Linux 的 LiveCD。 使用UUID将 btrfs 的顶层子卷挂载到/mnt

# mount -t btrfs -o subvol=/ /dev/disk/by-uuid/UUID_of_root_volume /mnt
# cd /mnt

将目前的子卷移动到其他地方,例如将 @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 快照来创建新快照。

# btrfs subvolume snapshot @home-backup/.snapshots/number/snapshot @home

.snapshots 移回恢复完成的子卷下,例如@home


# mv @home-backup/.snapshots @home/
注意:如果在 fstab中指定的是 subvolid 而不是子卷路径,则需要更改 /mnt/@/etc/fstab 中的 subvolid(假定把@子卷挂载到了/)。 可以使用 btrfs subvolume list /mnt | grep @home$ 来查询新的 subvolid


重新启动计算机。

检查计算机运行是否正常。这时可以删除在还原之前创建的快照了——例如@home-backup。在删除前记得检查是否有需要保留的数据。

删除快照

要删除序号为 N 的快照:

 # snapper -c config delete N

可以一次删除多个快照。例如,要删除 root 配置文件的 65 和 70 号快照:

 # snapper -c root delete 65 70

要同时删除多个连续的快照,例如删除 65 到 70 号所有快照:

# snapper -c root delete 65-70

要立即释放快照占用的磁盘空间,使用 --sync 选项:

# snapper -c root delete --sync 65

要删除一个 Snapper 配置和其所有快照,包括 .snapshots 子卷:

# snapper -c config delete-config 
注意:删除 pre 快照时, 你应该总是删除对应的 post 快照。反之亦然。

允许非 root 用户访问

所有配置文件都是由 root 用户创建的,默认情况下,也只有 root 用户可以查看并访问它们。

要让指定用户可以列出某一配置文件的快照,修改 /etc/snapper/configs/config 中的 ALLOW_USERS 项。现在你应该可以以普通用户权限运行 snapper -c configlist

最后,如果你想允许某一用户浏览 .snapshots 目录,但是该目录的拥有者必须为 root。因此,你应该修改包括该用户的组为组拥有者,以 users 为例:

# chmod a+rx .snapshots
# chown :users .snapshots

提示与技巧

在进行 pacman 操作时创建快照

下列软件包可以依据 pacman 进行的事务自动创建快照。

https://github.com/wesbarnett/snap-pac || snap-pac
  • grub-btrfs — 包含了一个名为 grub-btrfsd 的 systemd 单元。可自动查找快照并将其添加到 GRUB 菜单中。
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 命令以供创建 pre/post 快照(例如snp pacman -Syu)相比 Snapper 自身的 --command 选项能更好的处理输出重定向(参见 #pre/post 快照)。
https://gist.github.com/erikw/5229436 || snpAUR
https://gitlab.com/Zesko/limine-snapper-sync || limine-snapper-syncAUR

启动到只读快照中

使用 grub-btrfssnap-pac-grubAURlimine-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 issue

进一步了解:

提示:你可以使用 Limine 启动到快照中。Limine 和 Snaper 间的集成由 limine-snapper-syncAUR 提供。参见Limine#Snapper snapshot integration for Btrfs

在进行 pacman 事务时备份非 btrfs /boot 分区

如果你的 /boot 分区是在一个非 btrfs 文件系统上(例如一个 ESP 分区),Snapper 无法备份这些分区。 在系统备份#快照与_/boot_分区中提供了一个自动在内核更新时将 /boot复制到你的 btrfs 根目录下的方法。这种方法也能和 snap-pac 一起使用。

增量备份到外部驱动器

一些工具可以使用 Snapper 进行自动备份。参见 Btrfs#增量备份到外置设备

建议的文件系统布局

注意:下列布局是为了与 snapper rollback 搭配使用。而是为了缓解#Restoring / to its previous snapshot 中的某些问题。参见 论坛帖子

这是一种建议的文件系统布局,可以方便的将挂载到 /@ 子卷还原到之前的状态:

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

子卷@...应当挂载到任何应有自己子卷的目录。

注意:
  • 当对 @ 子卷(挂载到/)创建快照时,其余子卷的将不会被包含在快照中。即使这些子卷位于 @ 之下(子卷不是递归包含的)。如果需要为其他子卷创建快照,需要单独为这些子卷创建 Snapper 配置。
  • 由于Btrfs 的限制,需要创建快照的子卷中不能包含swap 文件。将 swap 文件放到另外的子卷或者使用 swap 分区

如果你想将@子卷恢复到之前的状态,其他的子卷将不会被影响。例如,当你在将@恢复到之前的快照时,/home将不会受到影响,因为/home挂载到了单独的子卷下。

这个布局能使 Snapper 定期为 /创建快照,并能让在出现启动问题时更容易还原快照。

在这种情况下,进行初始设置之后,Snapper不需要更多配置。

提示:
  • 考虑为其他不想包含在@快照中的目录创建子卷。例如 /var/cache, /var/spool, /var/tmp, /var/lib/machines (systemd-nspawn), /var/lib/docker (Docker), /var/lib/postgres (PostgreSQL),或是其他 /var/lib/ 下的目录。你可以使用类似上面的平行子卷结构,或是创建下层子卷。但是,pacman 数据库 /var/lib/pacman 必须位于挂载到/的子卷下。
  • 你可以为@home或是其他子卷单独创建快照或者还原快照。

配置 Snapper 和挂载点

假定@挂载到了/下,同时 /.snapshots 未被挂载,同时也不存在同名目录。可以使用如下命令确认:

# umount /.snapshots
# rm -r /.snapshots

接下来为/#建立一个新的配置。Snapper 会自动在@下创建 .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 创建的快照储存在 @ 之外。所以 @ 被还原或替换时也不会丢失快照。

还原到之前的快照

要将 / 还原到某个快照的状态,首先启动到 Arch Linux Live 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/@

为 Snapper 创建的快照创建一个可读写快照:

# btrfs subvolume snapshot /mnt/@snapshots/number/snapshot /mnt/@

number 替换为你想还原的快照序号。

注意:如果在 fstab中指定的是 subvolid 而不是子卷路径,则需要更改 /mnt/@/etc/fstab 中的 subvolid(假定把@子卷挂载到了/)。 可以使用 btrfs subvolume list /mnt | grep @$ 来查询新的 subvolid。另外若在启动加载器中使用了 subvolid,也需要一并更改。例如 refind_linux.conf

最后,卸载顶层子卷(subvolid=5),挂载@/mnt以及 ESP分区。chroot到完成还原的根目录下,并重新生成 initramfs

现在/已经恢复到了之前快照的状态。重新启动计算机。

提示:你也可以使用为这种布局设计的自动回滚工具:snapper-rollbackAUR。编辑 /etc/snapper-rollback.conf 来匹配系统的实际布局情况。

还原其他子卷到之前的状态

参见#还原快照

从快照中删除文件

若你想删除指定的文件或文件夹而不想删除整个快照,可以使用 snappersAUR 实现。这个脚本还可用于以 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,阻止.snapshots索引该目录:

/etc/updatedb.conf
PRUNENAMES = ".snapshots"

禁用配额

Btrfs 的配额功能(不是后来引入的“简单配额”(simple quota))可能会导致删除快照时占用大量 CPU 来维护配额信息。

要确定配额是否已启用,使用如下命令:

# btrfs qgroup show /

可以使用如下命令禁用配额:

# btrfs quota disable /

计算快照数量

如果禁用配额没有减缓性能问题,那么计算快照数量可能会有用:

# btrfs subvolume list -s / | wc -l

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

如果目录中包含用户数据(如电子邮件或日志),建议将其存储在自己的子卷而不是根子卷 / 中。这样,如果恢复 / 的快照,用户数据和日志不会受到影响。可以为用户数据使用单独的 timeline。不建议为 /var/log 创建日志快照。这可能会导致难以排除故障。

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

依据磁盘使用量清理快照

这篇文章的某些内容需要扩充。

原因:See [3] for ideas. (在 Talk:Snapper 中讨论)


疑难解答

日志

Snapper 将所有活动写入到 /var/log/snapper.log 中——在你认为出错时,首先检查该文件。

当你遇到关于每小时/每日/每周快照的问题时,最常见的原因是由于 cronie 服务(或者你使用的其他 cron 守护进程)没有运行。

IO 错误

如果你在试图创建快照时遇到 'IO Error',请确认你试图创建快照的子卷对应的 .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 

第二个命令列出的子卷但未出现在第一个命令的输出中的都是未被 snapper 管理的快照。可以手动删除

相关资源