利用 Snapper 实现 btrfs 自动定时备份
snapper 是一个由 openSUSE 开发的 Btrfs/LVM 快照管理软件。它可以自动创建和清理快照序列,在快照之间进行比较,回滚到之前的快照等,能够帮助我们充分利用 btrfs 的高级特性。
[2017-03-15] 作者翻译了一下 ArchWiki 的相关页面,欢迎查阅。
安装
ArchLinux 用户安装 community/snapper 即可。 AUR/snapper-gui-git 提供了一个非官方 GUI 界面,可以选择性安装。
sudo pacman -S snapper
yaourt -S snapper-gui-git
snapper 工作在 btrfs 上时,以 btrfs 子卷(subvolume)为操作单位。因此在使用 snapper 以前,你必须已经创建好 btrfs 子卷。合理将你的文件分散到不同子卷中会带来很大便利。
创建配置文件
首先需要为 snapper 要管理的 btrfs subvolume 创建配置文件,执行以下命令将根据默认配置模板 /etc/snapper/config-templates/default 创建一个配置文件。
snapper -c configname create-config /path/to/subvolume
# examples
snapper -c arch_rootfs create-config /
snapper -c home create-config /home
默认配置文件包括以下内容,更多内容可以 man snapper-configs 查看。
# 要创建快照的子卷
SUBVOLUME="/"
# 文件系统类型
FSTYPE="btrfs"
# 清理算法将使用的 btrfs qgroup,用于空间配额限制,仅用于 btrfs
QGROUP=""
# 快照占用的总空间限制,0.5 = 50%
SPACE_LIMIT="0.5"
# 允许访问该配置的用户和用户组,其他用户无法使用 snapper 操作该配置文件及对应快照
ALLOW_USERS=""
ALLOW_GROUPS=""
# 是否将以上的被允许用户和用户组写入到快照的ACL以允许他们访问快照
# 只有能够访问快照的用户才能进行查看、比较等操作
# 快照只能由 root 用户拥有,并且不能对其他用户可写
SYNC_ACL="no"
# 后台自动创建后续快照后是否比较前后快照
BACKGROUND_COMPARISON="yes"
# 是否运行基于数量的清理算法
NUMBER_CLEANUP="yes"
# 基于数量清理使用的参数
# 允许清理的最小快照创建时间,单位为秒
NUMBER_MIN_AGE="1800"
# 保留的快照数目,多余快照将被清理,优先保留新快照
NUMBER_LIMIT="50"
# 保留的重要快照数目
NUMBER_LIMIT_IMPORTANT="10"
# 是否创建每小时快照
TIMELINE_CREATE="yes"
# 是否运行基于时间的清理算法
TIMELINE_CLEANUP="yes"
# 基于时间清理使用的参数
# 允许清理的最小快照创建时间,单位为秒
TIMELINE_MIN_AGE="1800"
# 保留的每小时快照数量,以下同
TIMELINE_LIMIT_HOURLY="10"
# 每日快照为每天创建的第一个快照,以下同
TIMELINE_LIMIT_DAILY="10"
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="10"
TIMELINE_LIMIT_YEARLY="10"
# 是否清理前后无变动的快照
EMPTY_PRE_POST_CLEANUP="yes"
# 清理前后无变动快照时的限制参数
EMPTY_PRE_POST_MIN_AGE="1800"
启动定时器
要使用 systemd timer 运行 snapper。启动并启用 snapper-timeline.timer 来启用自动创建快照功能。启动并启用 napper-cleanup.timer 来启用自动清理功能。
systemctl enable --now snapper-timeline.timer
systemctl enable --now snapper-cleanup.timer
查看快照
snapper -c configname list
# example
snapper -c home list
# output
类型 | # | 前期 # | 日期 | 用户 | 清空 | 描述 | 用户数据
-------+---+----------+---------------------------------------------+--------+----------+----------+-------------
single | 0 | | | root | | current |
single | 1 | | 2017年03月14日 星期二 17时27分56秒 | root | timeline | timeline |
single | 2 | | 2017年03月14日 星期二 20时00分57秒 | root | timeline | timeline |
single | 3 | | 2017年03月14日 星期二 21时00分52秒 | root | timeline | timeline |
比较快照
snapper -c configname status number1..number2
# example
snapper -c home status 1..3
回滚快照
snapper -c configname rollback [number]
- 不带 number 参数时。将为默认子卷创建一个只读快照,再为当前子卷创建一个读写快照,并将默认子卷设置为后者。
- 带 number 参数时。将为当前子卷创建一个只读快照,再为指定 number 的快照创建一个读写快照,并将默认子卷设置为后者。
删除快照
snapper -c configname delete number1
snapper -c configname delete number1..number2
# example
snapper -c home delete 1
snapper -c home delete 1..3
比较文件内容
snapper -c configname diff number1..number2 [filename]
# example
snapper -c home diff 1..3 ~/.z
回滚文件内容
snapper -c configname undochange number1..number2 [filename]
# example
snapper -c home undochange 1..3 ~/.z