用 Ubuntu 快照服务固定软件包状态,重现历史安装环境

未完纪 · Linux与网络防护 · WWJ-587

同样的安装命令,在不同日期可能得到不同的软件包。Ubuntu 快照服务把软件仓库的时间也变成一个可以指定的参数:既能临时查询历史版本,也能固定某个仓库或整台机器的更新基线。

原作者:Canonical / Ubuntu Server 文档贡献者(团队署名,原页未列个人署名)
原文:How to use the Ubuntu snapshot service · 原页最后更新:2026-07-02 · 中文翻译与技术注:未完纪 · 核验日期:2026-10-05

快照服务解决什么问题

Ubuntu 快照服务让你按过去的日期和时间访问 Ubuntu 软件包归档。它主要适合三类任务:

  • 安装在特定时刻存在、后来已被新版本取代的软件包,以重现问题、排查回归或提高构建的可复现性。
  • 把升级目标固定到已知状态,让一批 Ubuntu 机器保持一致,也让包括无人值守升级在内的软件更新更可预测。
  • 支持分阶段更新流程:先在不同环境中验证同一个快照,再向大批机器逐步推广。

下面分别介绍临时命令参数、按仓库固定和全局固定三种方式。这里固定的是软件仓库视图,不是整个操作系统的磁盘快照,也不会自动恢复配置文件、业务数据或已经完成的包安装。

先确认系统和 APT 版本

快照功能从 Ubuntu 23.10 开始提供,也已回移到更新后的 Ubuntu 20.04 LTS 和 22.04 LTS:前者要求 apt 至少为 2.0.10,后者至少为 2.4.11。

Ubuntu 24.04 LTS 及之后版本的 APT 可以自动判断仓库是否支持快照,因此使用 Ubuntu 快照服务前通常不需要额外启用。低于 24.04 的版本则需要在相应的软件源条目上设置 snapshot 选项。原文汇总如下:

Ubuntu 版本 是否支持快照 是否需要配置软件源
24.04 之后的版本 支持 不需要额外启用
24.04 LTS 支持 不需要额外启用
22.04 LTS apt >= 2.4.11 需要
20.04 LTS apt >= 2.0.10 需要

版本注:这里列的是功能支持条件,不是各发行版的安全维护期限。原文提及 23.10 是为说明功能起点,不应据此把它选作新部署的受支持基线。还应确认实际仓库提供快照;第三方仓库不会因为 Ubuntu 支持这一功能便自动具备历史归档。

以 Ubuntu 22.04 的 /etc/apt/sources.list 为例,假设当前内容如下:

deb http://archive.ubuntu.com/ubuntu jammy main universe restricted multiverse
deb http://archive.ubuntu.com/ubuntu jammy-updates main universe restricted multiverse
deb http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse

在每个条目加入 [snapshot=yes],即可对这些 pocket(仓库分区)中的全部组件启用快照:

deb [snapshot=yes] http://archive.ubuntu.com/ubuntu jammy main universe restricted multiverse
deb [snapshot=yes] http://archive.ubuntu.com/ubuntu jammy-updates main universe restricted multiverse
deb [snapshot=yes] http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse
deb [snapshot=yes] http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse

低于 Ubuntu 24.04 的版本如果缺少这项配置,APT 会忽略快照相关的命令行选项。关于组件和 pocket 的区别,可参见 Ubuntu 软件包归档说明。修改实际机器时应保留原有镜像地址、架构限制和组件;不要把示例里的 jammy 直接覆盖到其他发行版的软件源中。

快速开始:给安装命令加一个时间戳

满足前提条件后,可以直接在 apt 命令中指定快照。原文用下面的命令演示安装 hello 包:

sudo apt install hello --update --snapshot 20240301T030400Z

--update 表示先取得软件包信息,再完成安装;--snapshot 后面的值决定使用哪个时间点的归档。命令会修改系统上的包状态,应在合适的测试环境中使用。

理解快照 ID

后文用 $SNAPSHOT_ID 表示快照 ID。它是 UTC 时间,格式为 YYYYMMDDTHHMMSSZ。例如 20240430T214500Z 表示 2024 年 4 月 30 日 21:45:00 UTC 的 Ubuntu 归档状态。原文说明,服务可提供 2023 年 3 月 1 日之后的日期与时间对应的快照。

占位符注:命令中的 $SNAPSHOT_ID 和 $PACKAGE_NAME 是 shell 变量占位符,执行前应赋值或替换成实际值。配置文件中的同名字符串只是示意,APT 不会替你进行 shell 变量展开,必须写入具体快照 ID。下文里的 ... 表示省略内容,不能当作完整软件源配置粘贴。

快照选择优先级:仓库条目中的固定 Snapshot 值优先于命令行 --snapshot,命令行值优先于全局 APT::Snapshot;无快照设置时使用常规软件仓库
图 1:快照选择关系。原创示意图依据原文三个配置方式绘制,仅针对支持并启用快照的仓库。

方式一:在命令行临时选择快照

APT 接受 --snapshot,也接受短选项 -S。可以先更新指定快照的索引,再用同一快照安装包:

sudo apt update --snapshot $SNAPSHOT_ID
sudo apt install $PACKAGE_NAME --snapshot $SNAPSHOT_ID

也可以将读取包信息和安装合并成一条命令:

sudo apt install $PACKAGE_NAME --update --snapshot $SNAPSHOT_ID

短选项形式等价:

sudo apt install $PACKAGE_NAME --update -S $SNAPSHOT_ID

原文把这个合并写法称为“atomic”。在这里可理解为一次命令完成这两个动作,不能据此推断包安装及维护脚本具备数据库式的事务回滚保证。

例子:查询 Ubuntu 24.04 初期的 Docker 包

若要查看 Ubuntu 24.04 LTS 刚发布时的 Docker,可以选择 2024 年 5 月 1 日 12:00 UTC 的快照:

sudo apt update --snapshot 20240501T120000Z

原文勘误:对应叙述写成了“May 2025”,但命令时间戳为 20240501T120000Z。本文按命令和“24.04 刚发布”这一上下文统一写为 2024 年 5 月;命令本身不变。

之后每次希望操作同一个快照,都要继续传入快照选项。例如查询 Docker 候选版本:

apt policy docker.io --snapshot 20240501T120000Z

原文输出:

docker.io:
  Installed: (none)
  Candidate: 24.0.7-0ubuntu4
  Version table:
     24.0.7-0ubuntu4 500
        500 https://snapshot.ubuntu.com/ubuntu/20240501T120000Z noble/universe amd64 Packages

如果遗漏选项,APT 就会使用常规归档,而不是延续上一条命令选择的快照:

apt policy docker.io

原文当时的常规归档输出如下,版本号只用于对比两种查询的差异:

docker.io:
  Installed: (none)
  Candidate: 28.2.2-0ubuntu1~24.04.1
  Version table:
     28.2.2-0ubuntu1~24.04.1 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages
     27.5.1-0ubuntu3~24.04.2 500
        500 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages
     24.0.7-0ubuntu4 500
        500 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages

接下来,从选定的快照安装 Docker:

sudo apt install docker.io --snapshot 20240501T120000Z

docker --version

原文省略了中间安装日志,给出的版本输出为:

Docker version 24.0.7, build 24.0.7-0ubuntu4

根据发布历史选择另一个版本

假设查询 Launchpad 的 Docker 软件包发布历史后,需要安装 26.1.3-0ubuntu1~24.04.1。原文根据发布记录说明:该版本在 2024 年 11 月 25 日于 noble-updates 取代了 24.0.7-0ubuntu4.1,后者于 11 月 26 日从 -updates 分区移除。因此例子选择 20241126T230000Z:

sudo apt install docker.io --update --snapshot 20241126T230000Z

docker --version

原文省略中间安装日志后的输出为:

Docker version 26.1.3, build 26.1.3-0ubuntu1~24.04.1

原文安全提示:原文写作时,noble-security 中的 docker.io 已为 27.5.1-0ubuntu3~24.04.2。因此,上例中的旧版本可能受已知漏洞影响。使用快照服务时,要核对当前发行版 -security 分区中的版本,避免把“能重现历史环境”误当成“适合继续安全运行”。本文没有将原文中的安全仓库版本更新成未经验证的“当前最新”值。

还要注意,换到旧仓库视图并不意味着 APT 会自动把已经安装的新包降级。原例从未安装状态开始,并在后续演示升级;若要做降级或跨版本恢复,需要另外检查依赖、维护脚本与数据格式,本指南没有覆盖这种操作。

方式二:为指定仓库固定快照

可以在 APT 软件源配置里,为每个仓库单独指定快照。使用 deb822 格式时,在相应 .sources stanza 中添加:

Snapshot: $SNAPSHOT_ID

若使用 Ubuntu 22.04 LTS 及更早版本常见的单行 /etc/apt/sources.list 格式,把此前的 yes 换成具体 ID:

deb [snapshot=$SNAPSHOT_ID] http://archive.ubuntu.com/ubuntu ...

例如,要为 Ubuntu 24.04 LTS 的全部标准 pocket 固定快照,可以在 /etc/apt/sources.list.d/ubuntu.sources 写入以下内容。两个 stanza 用空行分隔:

Types: deb
URIs: http://archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Snapshot: 20250530T223000Z

Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: noble-security
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Snapshot: 20250530T223000Z

排版核验:快照 ID 必须连续书写。网页文本提取曾把它显示为 20250530 T223000Z;已对照官方 Markdown 源文 确认应为 20250530T223000Z。本文也补上 deb822 两个 stanza 之间应有的空行。

此后安装命令不必再携带快照选项,APT 会按软件源配置获取该时间点的软件包:

sudo apt install --update docker.io
docker --version

原文对应输出:

Docker version 27.5.1, build 27.5.1-0ubuntu3~24.04.1

这个方式有一个关键规则:仓库条目里固定的快照会覆盖命令行的快照选择。原文为了演示该规则,传入另一个时间戳:

# 原文示例:此时间戳省略了秒
sudo apt install --update docker.io --snapshot 20251013T2300Z

源文日志仍指向在配置文件中固定的 2025 年 5 月 30 日快照:

...
Hit:5 https://snapshot.ubuntu.com/ubuntu/20250530T223000Z noble InRelease
Hit:6 https://snapshot.ubuntu.com/ubuntu/20250530T223000Z noble-updates InRelease
Hit:7 https://snapshot.ubuntu.com/ubuntu/20250530T223000Z noble-backports InRelease
Hit:8 https://snapshot.ubuntu.com/ubuntu/20250530T223000Z noble-security InRelease
...
docker.io is already the newest version (27.5.1-0ubuntu3~24.04.1).
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.

时间戳注:上面原例的 20251013T2300Z 不符合本文先前定义的含秒格式。按 23:00:00 的意图补全应写 20251013T230000Z。这里保留原文命令供核对;不把它当作已验证可接受的输入。该段要说明的是配置优先级,不是短时间戳格式的兼容性。

只要相应仓库的 Snapshot 仍是固定值,单独改变命令行选项就不会切换它。尤其当 noble-security 也被固定时,后续安全修复不会自动进入这个固定时间点;变更前应记录现有配置,变更后确认实际索引 URL 和候选版本。

方式三:给所有已启用快照的仓库设置全局默认值

另一种做法是设置全局 APT::Snapshot,让支持并启用快照的仓库共用默认时间点。

原文提醒:如果一路跟随上一节操作,先撤销软件源文件里的固定 Snapshot 修改,再测试这一节;否则仓库固定值仍会优先,观察不到预期的全局切换效果。撤销时应恢复你自己的原始配置,而不是盲目覆盖整份源文件。

原文通过以下命令创建全局配置:

echo 'APT::Snapshot "20250801T111111Z";' | sudo tee /etc/apt/apt.conf.d/50snapshot

写入边界:这条命令会以管理员权限写入 /etc/apt/apt.conf.d/50snapshot,如果该文件已存在,内容会被覆盖。先检查它是否属于自己此前创建的配置,并保存需要保留的原内容。

系统现在默认从这个快照读取包:

sudo apt install docker.io --update
docker --version

原文省略安装日志,输出为:

Docker version 27.5.1, build 27.5.1-0ubuntu3~24.04.2

与按仓库固定不同,全局默认值允许被命令行覆盖。例如:

sudo apt install docker.io --update --snapshot 20251013T120000Z
docker --version

原文输出变为:

Docker version 28.2.2, build 28.2.2-0ubuntu1~24.04.1

如果不再需要这个全局默认值,可移除刚才创建的配置文件:

sudo rm /etc/apt/apt.conf.d/50snapshot

删除与恢复注:这条命令只应删除确认由本例创建、且不含其他必要配置的 50snapshot 文件;它不会还原此前安装的软件包,也不会撤销写在软件源中的固定快照。若文件原本已有内容,应恢复备份或仅移除对应配置项。重新读取正常仓库并确认候选版本后,才算完成更新来源的恢复检查。

把快照纳入更新流程

临时命令参数适合一次查询或验证;按仓库固定适合明确要求某些仓库始终采用同一历史状态的场景;全局配置适合设定统一默认基线,同时允许单次命令切换。三者都应记录快照 ID、Ubuntu 发行版、软件源配置和选中的包版本。这样,后续看到差异时才能判断是仓库状态、已安装包还是其他环境因素发生了变化。

原文的进一步阅读包括:Ubuntu 快照服务官方页面与文档、在尽量保持可用性的同时保护多台 Ubuntu 实例,以及 把 Ubuntu 快照服务集成到系统管理和更新工具。

来源与许可:本文完整翻译整理自 Canonical / Ubuntu Server 文档贡献者的 How to use the Ubuntu snapshot service,并对照了该页的 官方 Markdown 源文。原页版权栏为“Copyright © 2026”,未列个人作者,也未在本页明确给出独立许可名称;本稿不臆造一个 CC 许可。保留团队归属与原文链接;不表示 Canonical 背书。中文标题、原创图、衔接说明及标为“注”的勘误和操作边界为本次编辑加工,原命令及历史输出按文中说明保留。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容