从 Restic 备份恢复数据:先选快照,再选文件

作者:restic 项目贡献者。本文依据官方 Restoring from backup 全文翻译整理,核对版本为 restic 0.19.1(2026-10-05)。文中命令是操作说明,本次仅做静态审查,未连接仓库或执行恢复。路径、主机名和快照 ID 沿用官方示例,使用时必须换成已核对的实际值。

Restic 的恢复流程可以分成三个决定:取哪个时间点的快照,取快照中的哪些文件,以及把它们写到哪里。把这三件事分开考虑,能避免最常见的错误:选中了正确的快照,却恢复了过多文件;或者找到了正确文件,却覆盖了正在使用的数据。

Restic 恢复流程:选择快照、选择文件、预演、恢复到独立目录并核验;原位覆盖和删除属于需额外确认的分支。
原创技术示意图:未完纪整理。表示操作关系,不是软件界面或运行截图。

从快照恢复到独立目录

已知快照 ID 时,可以把内容还原到指定目录。下面的 79766175 是特定快照,不能把它理解为“自动选择最新快照”。官方开头的文字称“最新”,但紧随的命令明确给出了固定 ID;这里按命令真实含义说明。

restic -r /srv/restic-repo restore 79766175 --target /tmp/restore

要选择最新快照,使用 latest。它可以与 --host、--path 联合使用:

restic -r /srv/restic-repo restore latest --path /home/art --host luigi --target /tmp/restore

--path 在这里仅用于挑选快照,不会限制恢复文件的范围。 如果选中的快照同时包含 /home/art 和 /home/documents,这两个目录都会恢复,分别位于 /tmp/restore/home/art 与 /tmp/restore/home/documents。

只恢复需要的文件或子目录

限制文件范围要用 --include 或 --exclude,两者互斥。例如只取回一个文件:

restic -r /srv/restic-repo restore 79766175 --target /tmp/restore --include /home/user/work/foo

结果位于 /tmp/restore/home/user/work/foo。先用 restic ls latest 或 restic find foo 查明文件在快照树里的路径,再将该路径原样传给完整快照恢复命令的 --include。

如果只想从某个子目录开始恢复,可以使用 <snapshot>:<subfolder>。快照可以是 ID,也可以是 latest;子目录应当以 restic ls 显示的树为准:

restic -r /srv/restic-repo restore 79766175:/home/user/work --target /tmp/restore --include /foo

此时文件恢复到 /tmp/restore/foo,因为选定的子目录成为恢复树的根。--include 和 --exclude 的模式也要相对于这个子目录写,不能继续使用完整快照的路径。

忽略路径大小写时,可使用 --iinclude 与 --iexclude。如果模式很多,--include-file、--exclude-file、--iinclude-file、--iexclude-file 可以从文件读取模式。

元数据、稀疏文件与 Windows 权限

在 Windows 上,恢复符号链接要求用户拥有 SeCreateSymbolicLinkPrivilege,或者以管理员运行。恢复完整安全描述符需要 SeRestorePrivilege、SeSecurityPrivilege 与 SeTakeOwnershipPrivilege,或者管理员权限;权限不齐时,只恢复 DACL。这些限制来自 Windows。

Restic 默认不会把文件恢复为稀疏文件。若文件系统支持,可使用 restore --sparse,将连续的零字节恢复为不占用实际磁盘空间的“空洞”。读取空洞仍得到零字节,但空洞的位置由恢复时判断,未必与原文件完全一致,因为 Restic 没有显式记录原来的空洞位置。

文件扩展属性默认全部恢复。可以用互斥的 --include-xattr 或 --exclude-xattr 限定它们。例如:

restic -r /srv/restic-repo restore 79766175 --target /tmp/restore --include-xattr 'user.*' --include-xattr 'security.*'

这里给模式加了引号,这是相对原文的安全性调整,可避免 shell 把星号提前展开为当前目录的文件名。恢复安全命名空间属性仍受操作系统权限约束。

原位恢复:理解覆盖选项与中断后果

恢复到已有数据的目录时,默认会覆盖已有文件。若原位恢复被中断,文件可能停留在部分恢复状态。 官方建议先对当前状态再做一次备份,以便需要时退回。独立目录恢复通常更便于核对和比较。

选项 行为
--overwrite always 默认值。验证已有文件内容,仅下载并恢复不一致的部分;更新所有文件的元数据。
--overwrite if-changed 大小和修改时间相同就假定内容已是最新;不同时才完整校验内容。也会更新全部文件的元数据。此快捷判断无法发现“大小和 mtime 相同但内容不同”的情况。
--overwrite if-newer 仅在快照内文件的 mtime 更新时覆盖已有文件。
--overwrite never 不覆盖已存在的文件。

删除多余文件之前,必须检查预演

--delete 会删除目标目录中快照里不存在的文件,也允许用快照里的同名普通文件替换目标中的非空目录。它不是普通恢复所必需的选项。

使用 --include 或 --exclude 时,删除也受这些匹配规则限制。例如只包含 /foo 的子目录恢复,删除范围只在目标的 foo 中。官方 0.19.1 页面还说明:合用 --target 和 --delete 时,必须同时给出 include 或 exclude 选项,以防意外删除整个系统;不同版本应核对自身命令帮助,不能靠这个保护替代路径审核。

以下仅展示预演,不提供自动紧接实际删除的脚本:

restic -r /srv/restic-repo restore 79766175:/home/user/work --target /tmp/restore --include /foo --delete --dry-run -vv

即使不删除,也可以先预演恢复:

restic -r /srv/restic-repo restore --target /tmp/restore --dry-run --verbose=2 latest

输出中的 unchanged 表示内容已一致,updated 表示已有文件会改变,restored 表示新增文件;目录、符号链接等类型总显示为 restored。预演为了判断哪些文件会更新,也会按所选覆盖策略核验已有文件,因此它不一定很快。若要跳过这些校验,可以用 --overwrite never,或者指定尚不存在的目标目录。预演输出是计划,不能代替实际恢复后的验证。

把备份挂载成文件系统

只需要浏览快照或挑几个文件时,可以通过 FUSE 挂载仓库:

mkdir /mnt/restic
restic -r /srv/restic-repo mount /mnt/restic

然后在另一个终端或文件管理器中浏览。结束时在挂载进程所在终端按 Ctrl+C,或者卸载挂载点。FUSE 挂载适用于 Linux、macOS 和 FreeBSD。Linux 需要加载 fuse 内核模块,并确保 fusermount 位于 PATH;macOS 需要 FUSE-T 或 FUSE for macOS;FreeBSD 可能需要安装 FUSE 并加载模块(官方给出的模块加载命令为 kldload fuse)。

挂载点不能与本地仓库目录重叠:不能使用仓库本身、仓库内部目录或仓库的父目录。否则 FUSE 服务可能通过新挂载读取自己的后端文件,造成内核死锁;当前 restic mount 会检测并拒绝这种路径。

Restic 能保存硬链接,但从 FUSE 挂载复制出来时,复制工具也必须保留硬链接,例如使用 rsync --hard-links。恢复大量文件或整个快照时,直接用 restic restore 通常更合适,官方指出它常常明显更快;本文未实测性能。

用 dump 导出到标准输出或归档文件

dump 可以把单个文件写到标准输出,交给其他工具使用。原文演示把 SQL 直接管道送入 mysql,这会立即执行备份中的 SQL,并可能写入默认连接到的数据库。本文改为先导出到受控文件,属于编辑安全修订:

restic -r /srv/restic-repo dump 098db9d5 production.sql > restored-production.sql

重定向也会覆盖已有同名文件,应在受控的独立工作目录使用。核对 SQL、目标实例和所需权限之后,再制定导入步骤,不能将备份内容视为可信可执行指令。

同一仓库备份多个路径时,无筛选的 latest 可能指向不包含目标文件的快照。可以明确给出 ID,或者用与 snapshots 输出中 Paths 列完全匹配的路径选取最新快照:

restic -r /srv/restic-repo snapshots
restic -r /srv/restic-repo dump --path /production.sql latest production.sql > restored-production.sql

如果备份时使用相对路径,快照列表中的路径不一定与快照内部树相同。先用 restic ls <快照ID> 查明实际布局。

dump 还可以导出整个目录树,默认使用 tar,也可选择 zip:

restic -r /srv/restic-repo dump latest /home/other/work > restore.tar
restic -r /srv/restic-repo dump -a zip latest /home/other/work > restore.zip

以上归档内保留 /home/other/work 层级。若希望目录内容直接出现在归档根部,可结合子目录语法:

restic -r /srv/restic-repo dump latest:/home/other/work / > restore.tar

也可以不用 shell 重定向,直接给出目标文件:

restic -r /srv/restic-repo dump latest / --target /home/linux.user/output.tar -a tar

来源、署名与审查范围

原文与作者归属:restic 官方文档:Restoring from backup,restic 项目贡献者。© Copyright 2023, restic authors. 中文翻译及编辑标注:未完纪,2026-10-05。上游代码仓库采用 BSD 2-Clause License,版权声明为 Copyright (c) 2014, Alexander Neumann;本稿保留该归属,不把代码许可证推定为另行确认的文档许可证。

本文经过命令参数、覆盖与删除边界、路径和管道执行风险的静态核对;未执行任何 Restic 命令,未验证特定仓库、平台权限或恢复性能。未发现更多问题不代表没有漏洞。文中示意图为原创,不含来源网站截图。

原文完整示例输出

以下是官方文档提供的历史示例,不是本文执行记录;仓库密码提示不包含真实凭据。固定快照、主机筛选、文件筛选与子目录恢复的输出分别如下。

固定快照恢复

enter password for repository:
restoring snapshot of [/home/user/work] at 2015-05-08 21:40:19.884408621 +0200 CEST to /tmp/restore

主机与路径筛选

enter password for repository:
restoring snapshot of [/home/art,/home/documents] at 2015-05-08 21:45:17.884408621 +0200 CEST to /tmp/restore

单文件恢复

enter password for repository:
restoring snapshot of [/home/user/work] at 2015-05-08 21:40:19.884408621 +0200 CEST to /tmp/restore

子目录恢复

enter password for repository:
restoring snapshot of [/home/user/work] at 2015-05-08 21:40:19.884408621 +0200 CEST to /tmp/restore

扩展属性恢复

enter password for repository:
restoring snapshot of [/home/user/work] at 2015-05-08 21:40:19.884408621 +0200 CEST to /tmp/restore

恢复预演

unchanged /restic/internal/walker/walker.go with size 2.812 KiB
updated   /restic/internal/walker/walker_test.go with size 11.143 KiB
restored  /restic/restic with size 35.318 MiB
restored  /restic
[...]
Summary: Restored 9072 files/dirs (153.597 MiB) in 0:00

FUSE 挂载

enter password for repository:
Now serving /srv/restic-repo at /mnt/restic
Use another terminal or tool to browse the contents of this folder.
When finished, quit with Ctrl-c here or umount the mountpoint.

快照清单

ID        Date                 Host        Tags        Paths
----------------------------------------------------------------------
562bfc5e  2018-07-14 20:18:01  mopped                  /home/user/file1
bbacb625  2018-07-14 20:18:07  mopped                  /home/other/work
e922c858  2018-07-14 20:18:10  mopped                  /home/other/work
098db9d5  2018-07-14 20:18:13  mopped                  /production.sql
b62f46ec  2018-07-14 20:18:16  mopped                  /home/user/file1
1541acae  2018-07-14 20:18:18  mopped                  /home/other/work
----------------------------------------------------------------------

快照 e922c858 的实际目录树

snapshot e922c858 of [/home/other/work] at 2018-07-14 20:18:10.884408621 +0200 CEST by mopped filtered by []:
/other
/other/work

快照清单中,未筛选的 latest 是 1541acae,包含 /home/other/work,并不包含 production.sql。所需 SQL 在 098db9d5 中;快照清单的 Paths 与内部树布局也可能不同,因此以 ls 核对。

版权与许可全文

以下保留本页涉及的来源材料或示例代码的版权、许可条件与免责声明;各自适用范围依原声明。中文翻译及编辑标注:未完纪,2026-10-05。

LICENSE-UPSTREAM.txt

BSD 2-Clause License

Copyright (c) 2014, Alexander Neumann <alexander@bumpern.de>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容