Snapper 是 openSUSE 的 Arvin Schnell 开发的快照管理工具,可管理 Btrfs 子卷、采用精简配置的 LVM 卷,以及实验性支持的 Bcachefs 子卷。它可以创建和比较快照、在快照之间恢复,并支持自动快照时间线。
Installation
安装 snapper 软件包。
此外,还有图形界面工具 btrfs-assistant、snapper-gui-gitAUR 和 snapper-toolsAUR。
创建新配置
为 Btrfs 子卷创建 Snapper 配置之前,该子卷必须已经存在。如果不存在,应先创建子卷,再生成 Snapper 配置。
要为位于 /path/to/subvolume 的 Btrfs 子卷创建名为 config 的配置,运行:
# 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 /
注意 如果安装 Arch 时采用早于3.0.5版本的
archinstall 所建议的
Btrfs 分区布局
[1],那么
@.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 并添加以下设置,可将频率从每小时改为每5分钟:
[Timer]
OnCalendar=
OnCalendar=*:0/5
编辑 snapper-cleanup.timer 时,需要修改 OnUnitActiveSec。要把清理频率从每天改为每小时,添加:
[Timer]
OnUnitActiveSec=1h
参见systemd/Timers和systemd#Drop-in files。
手动快照
单独快照
Snapper 默认创建 single 类型的快照,它与其他快照没有特殊关联。
手动创建子卷快照:
# snapper -c config create --description desc
以上命令未指定清理算法,因此快照会永久保留,直到删除。
要设置清理算法,在 创建 后使用 -c 标志,并选择 number、timeline、pre 或 post。number 让 Snapper 定期删除超过配置文件规定数量的快照。例如,创建一个使用 number 算法清理的快照:
# snapper -c config create -c number
timeline 快照的行为参见自动时间线快照;pre和post的行为参见前后快照。
前后快照(pre/post)
另一类快照是 pre/post,旨在成对创建:一次重要变更之前创建 pre 快照,之后创建 post 快照,例如系统更新前后。
如果该变更能够通过单条命令执行,可以使用 snapper create --command 调用命令并自动创建前后快照:
# snapper -c config create --command cmd
提示 要在任意 shell 命令前后创建
pre/post,也可以使用
snp
AUR
shell 脚本,它的输出重定向比 Snapper 原生
--command 选项更好。
也可以手动创建前后快照。
首先创建 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 是指向
/proc/self/mounts 的符号链接,因此恢复它并不影响系统。(讨论见
Talk:Snapper。)
一些文件保存系统状态,例如 /etc/mtab,不应将它们恢复到以前的状态。Arch Linux 的默认配置会保证这一点。为方便用户,Snapper 允许忽略这些文件。/etc/snapper/filters/*.txt 和 /usr/share/snapper/filters/*.txt 中各文件的每一行指定一个匹配模式。Snapper 比较两个快照的差异时,会忽略匹配任意模式的文件及目录。过滤器不会阻止文件或目录进入快照;若要排除快照内容,应使用子卷或挂载点。
原文提示:本节事实准确性存在争议。
另请参阅 SLES 12 SP5 文档中的从快照中排除的目录。
使用默认布局恢复
原文提示:本节事实准确性存在争议。
采用 Snapper 默认布局时,每个快照都是子卷 .snapshots 目录内的下一级子卷,例如 @home。
原文提示:本节事实准确性存在争议。
原因: 不用于
/ 的子卷可以直接从当前系统恢复。以 root 登录,确认子卷未被使用,然后卸载即可。(讨论见
Talk:Snapper。)
要用 Snapper 快照恢复 /home,先从 Arch Linux Live USB或光盘启动。
使用 UUID,把 Btrfs 根卷挂载到 /mnt:
# mount -t btrfs -o subvol=/ /dev/disk/by-uuid/UUID_of_root_volume /mnt
# cd /mnt
原文提示:本节事实准确性存在争议。
原因: 此处针对 Arch Linux Live USB或光盘环境编写,在这种环境中不可能有正在运行的 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/
如果 fstab 中 /home 挂载项使用 subvolid 而不是 /path/to/subvolume,请修改 /mnt/@/etc/fstab 中的 subvolid,改为通过 btrfs subvolume list /mnt | grep @home$ 找到的新编号。这里假设 @ 是系统中挂载为 / 的子卷。
重新启动。
检查系统是否正常工作;如有需要,再删除旧的或损坏的快照,例如 @home-backup。删除前,应检查其中是否还有可以找回的有用数据。
使用 srt 恢复主目录
srt 是 Snapper 快照恢复工具。如果已为每个用户的主目录创建子卷,并按srt-README.md配置用户的 .snapshots 目录及 Snapper 配置,就可以通过基于对话框的终端界面,方便快捷地恢复用户主目录快照。
删除快照
删除编号为 N 的快照:
# snapper -c config delete N
可以一次删除多个快照。例如,删除 root 配置的65号和70号快照:
# snapper -c root delete 65 70
也可以删除一个编号范围,例如 root 配置的65至70号快照:
# snapper -c root delete 65-70
若要立即释放快照占用的空间,使用 --sync:
# snapper -c root delete --sync 65
删除某个配置的所有快照、.snapshots 子卷及 Snapper 配置文件:
# snapper -c config delete-config
注意 删除 pre 快照时,应同时删除对应的 post 快照;反之亦然。
允许非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 事务发生时自动创建快照:
- https://github.com/wesbarnett/snap-pac || snap-pac
- grub-btrfs:包含一个可通过 systemctl 启用的守护进程 grub-btrfsd,用于查找新快照,并自动加入 GRUB 菜单。要运行该守护进程,需安装可选依赖 inotify-tools。
- https://github.com/Antynea/grub-btrfs || grub-btrfs
- https://github.com/maximbaz/snap-pac-grub || snap-pac-grubAUR
- 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-btrfs、snap-pac-grubAUR 或 limine-snapper-syncAUR 的用户应注意:Snapper 默认创建只读快照,而从只读快照启动存在固有困难。许多服务,例如桌面管理器,需要可写的 /var 目录,因此从只读快照启动时会失败。
可以把快照改为可写,或者采用开发者认可的方式,借助 叠加文件系统 启动快照,使其行为类似 Live CD 环境。
注意 对该快照中文件的所有修改都不会保留,因为这个文件系统仅存在于内存中。
通过 overlayfs 启动快照:
延伸阅读:
在 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
└── @...
@... 子卷可挂载到其他需要独立子卷的目录。
注意
- 为
@(挂载于根目录 /)创建快照时,不会包含其他子卷。即使某个子卷嵌套在 @ 之下,@ 的快照也不会包含它。对于 @ 之外需要保留快照的子卷,应分别创建 Snapper 配置。
- 由于Btrfs限制,已创建快照的卷不能包含交换文件。应把交换文件放在其他子卷,或者创建交换分区。
把系统恢复到 @ 的先前快照时,其他子卷不受影响。例如,可以把 @ 恢复到旧快照,同时让 /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或光盘启动。
挂载顶层子卷,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 @$ 找到的新编号。如果引导加载程序配置,例如 refind_linux.conf,包含 subvolid,也需要同步修改。
最后卸载顶层子卷ID5,再将 @ 挂载到 /mnt,把 ESP 或启动分区挂载到适当位置。切换根目录进入已恢复的快照,以便重新生成initramfs镜像。
现在 / 已恢复到先前快照,只需重新启动。
提示 还可以使用为这种布局开发的自动回滚工具:
snapper-rollback
AUR
。编辑
/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文档中跳过特定路径的示例与原因。
按磁盘使用量清理
原文提示:本节有待补充。
Troubleshooting
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
第二份列表中存在、第一份列表中不存在的子卷就是孤立子卷,可以手动删除。
另请参阅
暂无评论内容