4 个版本 (2 个破坏性更新)

0.2.1 2023年6月20日
0.2.0 2023年4月7日
0.1.0 2023年2月20日
0.0.0 2022年12月26日

#277 in 文件系统

GPL-3.0-or-later

135KB
3K SLoC

pipeline crates.io rustc

btrfs-backup

btrfs-backup 是一个可以用于备份一个或多个 btrfs 文件系统数据的程序。它依赖于 btrfs(8) 工具程序来执行其任务,并提供一个非常简单的接口,用于快速创建和传输 btrfs 快照。

至于 btrfs 文件系统本身,备份的单位是子卷。子卷的快照创建是基于需求的,也就是说,只有当检测到相应的子卷上有新数据可用时,才会创建新的快照。数据传输可以增量进行,也就是说,只需要发送最新快照状态的变化。

程序以仓库为推理单位。仓库是一个目录,用于包含新创建的以及已存在的快照。

在备份方面,涉及两个仓库:源仓库和目标仓库。通过从源到目标的快照文件增量传输,保持这两个仓库同步。在目标仓库上,随后将快照重新声明或存储在文件中。

用法

假设你有两个子卷,你想将它们备份到挂载在 /mnt/backup 的外部硬盘上

# Mount some backup drive.
$ mount /mnt/backup/
# Create a fake hierarchy of btrfs subvolumes for illustration purposes.
$ mkdir /.btrfs-root/
$ mkdir /.btrfs-root/subdir
$ btrfs subvolume create /.btrfs-root/subvol1
$ btrfs subvolume create /.btrfs-root/subdir/subvol2
/.btrfs-root/
├── subdir
│   └── subvol2
└── subvol1

备份

在这个配置中,备份可以非常简单

$ btrfs-backup backup \
    /.btrfs-root/subvol1 \
    /.btrfs-root/subdir/subvol2 \
    --destination /mnt/backup/

此命令会导致以下备份快照

/mnt/backup/
├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-20_11:14:35_
└── <hostname>_.btrfs-root-subvol1_2023-02-20:11:14:35_

btrfs 文件系统上的备份工作方式是,在源文件系统上创建要备份的子卷的只读快照,然后发送到目标文件系统。上面显示的是目标文件系统上的快照。因为我们没有向命令提供 --source 参数,所以源文件系统上的快照与实际的子卷位于同一位置(即它们位于相同的父目录中)

/.btrfs-root/
├── <hostname>_.btrfs-root-subvol1_2023-02-20_11:14:35_
├── subdir
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-20_11:14:35_
│   └── subvol2
└── subvol1

如果您想集中管理快照,请使用 --source 标志并提供指向 btrfs 文件系统上子卷所在目录的路径

# Create central snapshot location.
$ mkdir /snapshots
$ btrfs-backup backup \
    /.btrfs-root/subvol1 \
    /.btrfs-root/subdir/subvol2 \
    --source /snapshots \
    --destination /mnt/backup/

现在,快照不再位于子卷旁边

/.btrfs-root/
├── subdir
│   └── subvol2
└── subvol1

它们位于一个单独的目录中

/snapshots/
├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-20_11:14:35_
└── <hostname>_.btrfs-root-subvol1_2023-02-20_11:14:35_

恢复

子卷可以以类似的方式恢复,使用 btrfs-backuprestore 子命令。

# Let's say all our source data is gone and only /mnt/backup still
# available.
$ rm -rf /.btrfs-root
$ btrfs-backup restore \
    /.btrfs-root/subvol1 \
    /.btrfs-root/subdir/subvol2 \
    --source /mnt/backup/

本质上,我们现在使用 /mnt/backup 作为源存储库,并恢复原始子卷状态以及同位置的快照(如果提供 --destination 参数,则与集中管理的快照类似工作)。

/.btrfs-root/
├── <hostname>_.btrfs-root-subvol1_2023-02-20_11:14:35_
├── subdir
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-20_11:14:35_
│   └── subvol2
└── subvol1

清除

btrfs-backup 能够通过 purge 子命令识别并删除不再使用的快照。此子命令接受 --keep-for 参数,该参数理解持续时间指定,例如 2d(两天)、1w(一周)、5m(五个月)、1y(一年),并将删除超过该时间的快照。

例如,给定以下状态

/.btrfs-root/
├── <hostname>_.btrfs-root-subvol1_2023-01-31_19:56:07_
├── <hostname>_.btrfs-root-subvol1_2023-02-10_09:23:11_
├── <hostname>_.btrfs-root-subvol1_2023-02-20_11:14:35_
├── subdir
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-01-31_19:56:07_
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-10_09:23:11_
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-20_11:14:35_
│   └── subvol2
└── subvol1

以下命令

$ date
> Mo 20. Feb 11:15:53 PST 2023
# Delete all snapshots older than two weeks.
$ btrfs-backup purge \
    /.btrfs-root/subvol1 \
    /.btrfs-root/subdir/subvol2 \
    --destination /mnt/backup/ \
    --keep-for 2w

将导致从 2023-01-31 到的快照被删除,因为它们已经超过两周了。

/.btrfs-root/
├── <hostname>_.btrfs-root-subvol1_2023-02-10_09:23:11_
├── <hostname>_.btrfs-root-subvol1_2023-02-20_11:14:35_
├── subdir
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-10_09:23:11_
│   ├── <hostname>_.btrfs-root-subdir-subvol2_2023-02-20_11:14:35_
│   └── subvol2
└── subvol1

请注意,原始备份的子卷永远不会被删除——只会永远“清除”其快照。此外,最新的快照也会一直保留,以帮助未来的增量备份。

远程执行

在许多情况下,将子卷备份到远程主机(或从其中恢复子卷)是必需的。通过 SSHFS 等方式在本地挂载远程 btrfs 文件系统不会提供在该文件系统上使用 btrfs 特定工具的能力。为此,可以直接在远程主机上运行命令(前提是它提供了从外部执行命令的接口,并且已经安装了所需的 btrfs 工具套件)。SSH 是远程命令执行的典型示例。通过 SSH 连接使用 btrfs-backup 在远程主机上可以通过 --remote-command 参数实现,该参数可以提供给 backuprestore 以及 purge 子命令。例如:

$ btrfs-backup backup --remote-command='ssh server'
$ btrfs-backup backup \
    /.btrfs-root/subvol1 \
    /.btrfs-root/subdir/subvol2 \
    --destination /mnt/backup/ \
    --remote-command='ssh server'

此命令将通过 SSH 连接将快照传输到 server。它们将存储在远程系统上的 /mnt/backup 中。

快照标记

快照可以用一个任意字符串进行“标记”,该字符串将包含在快照名称中。可以通过各种子命令的 --tag 参数启用此操作。

当执行清除操作时,只会影响提供的标记的快照,而其他所有快照都将保持不变。这可以在子卷以不同频率备份到多个备份时很有用,因为它可以确保相关的快照不会被自动删除,以保留未来备份的增量特性。

此外,标记还起到信息作用:因为标记包含在快照的名称中,所以可以用来轻松识别子卷上次备份到特定备份位置的时间,例如。

有关详细信息,请参阅帮助文本(--help)。

安装

btrfs-backup 是用 Rust 编写的,需要 Cargo 包管理器来构建。可以使用以下命令进行安装:cargo install btrfs-backup。程序需要安装 btrfs-progs,并确保其 btrfs 二进制文件可以通过 PATH 环境变量找到。

状态

程序支持在同一系统上备份和恢复子卷,以及与远程系统之间的备份(例如,通过 ssh 连接)。它还可以自动清理过时的快照。因此,它可以完全满足备份需求。

与程序的原始 Python 版本 相比,快照命名方案已更改,并修复了一些错误。目前尚不支持将备份保存到文件(可能永远不会添加,因为它被认为是一个边缘功能,并且很少使用)。

依赖关系

约 5–16MB
约 193K SLoC