Insights / 技术解读
更新正在运行的 Ubuntu:事前准备、连接恢复与重启后检查
以从 Ubuntu 24.04 升级到 26.04 以及常规更新为例,具体说明如何实测恢复备份、留存配置、判断无人使用时能否停机、排查 SSH 无法恢复的情况,以及确认完成条件。

本文目录
- 选择24.04到26.04迁移还是常规更新
- 1. 确定更新类型和操作范围
- 2. 确保 SSH 断开后仍有其他操作通道
- 3. 将备份实际恢复到其他位置
- 4. 不只保存配置,还要记录“原有运行状态”
- 5. 把无人使用的瞬间转化为可安全停机的条件
- 区分“请求正常终止”和“正常终止已完成”
- 6. 常规更新要分开执行索引获取、计划检查和应用
- 如何处理分阶段更新中暂缓的软件包
- 7. SSH 无法恢复时,按顺序检查通信和启动
- cloud-init 重新生成网络配置时
- 8. 认证或启动兼容问题,仅检查适用的配置
- 使用 Samba 提供 Windows 域认证时
- 使用 SSSD 与外部认证基础设施集成时
- 更新中断、软件包或启动文件不完整时
- 9. 对照重启后的完成条件
更新运行中的 Ubuntu 服务器时,除了更新软件包,还必须执行停止服务、并在重启后恢复运维的步骤。SSH 连接中断、认证设置与新版本规范不兼容、无法读取备份等问题,可能会在更新命令结束后才出现。
本文把从 Ubuntu 24.04 升级到 26.04 的 LTS 升级及升级后的常规更新经验,整理成可应用于其他服务器的流程。前提是拥有管理员权限,并且能够安排包含服务停机的维护窗口。首先说明通用准备和操作步骤,后半部分排查连接、认证和启动问题。
选择24.04到26.04迁移还是常规更新
先判断是否需要新一代OS功能,还是当前版本修复已足够。发行版升级需增加外部认证、VPN和DB兼容性检查;常规更新主要核对软件包计划差异和重启影响。两者都应设定中止条件:恢复控制台或实际恢复验证不可用时不开始。
1. 确定更新类型和操作范围
首先确定是要更换 OS 版本,还是更新同一版本中的软件包。两者所需的变更量和检查事项并不相同。
| 操作 | 示例 | 使用的机制 | 事先检查事项 |
|---|---|---|---|
| 常规更新 | Ubuntu 26.04 内的修复和内核更新 | APT | 计划更新、添加、删除的内容,以及服务重启的影响 |
| 版本升级 | 从 Ubuntu 24.04 升级到 26.04 | do-release-upgrade |
官方升级条件、兼容性、已废弃或拆分的软件包 |
apt-get dist-upgrade是针对已配置的软件源调整依赖关系的命令。即使名称中包含“dist”,它也不是专门用于升级到下一个 Ubuntu LTS 版本的命令。版本升级应按照Ubuntu 官方步骤执行。生产环境中不采用添加面向开发版的-d,或只手动改写 APT 软件源的做法。从 Debian 切换到 Ubuntu 也不属于可通过此流程执行的升级。
目标不仅是主机名,还要确认该服务器所依赖的 DNS、认证、数据库以及连接用 VPN。若要更新多台服务器,应每次更新1台服务器,并确认依赖服务保持稳定。如果与其他维护工作或备份任务冲突,请先确定执行顺序。
此外,预先确定诸如“恢复失败”“无法获取所需软件包”“无法正常停止”“无法访问恢复控制台”等中止条件。与其在维护窗口结束前仍继续更新,不如预留出用于恢复的时间,这样更容易作出判断。
2. 确保 SSH 断开后仍有其他操作通道
更新前,先确认能从 VPS 或云服务的管理界面进入恢复控制台。不要只确认能打开页面;还必须具备实际操作 OS 的登录方式。仅有与 SSH 依赖同一个 VPN 或认证服务器的通道时,依赖服务停止后将无法恢复。
重启按钮只对临时停止或故障有效。配置错误或启动顺序问题会在重启后重现。在无法确认更新是否仍在进行的状态下,不要反复重启;应事先确保可以通过控制台检查当前状态。
如果使用服务提供商的磁盘映像,请查明映像获取期间是否会限制启动或操作、预计完成时间、存储容量和计费单位。若使用应用程序备份,还需要有重建 OS 并恢复配置的步骤。无论选择哪种方式,都应在作业前写明可恢复和无法覆盖的范围。
3. 将备份实际恢复到其他位置
即使备份任务显示成功,也不能保证其中包含所需数据或可以读回。更新前,把已确认目标主机、保存时间和保存内容的备份版本,恢复到一个空的验证目录。
例如,使用 restic 备份工具时,可在能够使用现有连接配置的管理员 shell 中按如下方式验证。将snapshot_id替换为已检查版本的 ID。固定指定 ID,而不使用latest,这样即使验证期间触发新的保存任务,目标也不会变化。
# 既存のリポジトリ接続設定を使う。秘密値をコマンドに直書きしない。
snapshot_id='確認したスナップショットID'
umask 077
restore_dir=$(mktemp -d /var/tmp/restore-check.XXXXXX) || exit 1
restic restore "$snapshot_id" --target "$restore_dir" --verify
不要将生产数据目录指定为恢复目标。restic 可以覆盖已有文件,因此应先查看官方恢复规范,并在隔离的空目录中验证。将备份的实际恢复纳入流程的方法也介绍了使用 R2 等对象存储的配置示例。
恢复后,根据数据格式检查以下内容。
| 数据 | 检查内容 | 单凭这一点无法确认的内容 |
|---|---|---|
| ZIP 等归档文件 | 解压、完整性检查,以及所需文件是否存在 | 应用程序能否启动并使用其中的内容 |
| SQL 转储 | 导入隔离的 DB、检查架构和主要数据 | 附件文件或外部存储的一致性 |
| SQLite | 恢复文件是否存在及其大小、DB 完整性检查 | 整个服务是否已恢复 |
| 配置、证书和密钥 | 目标文件、所有者、权限和引用位置 | 外部服务端的设置或有效性 |
直接复制运行中的 DB 文件,可能会混入保存过程中的不一致状态。应使用 DB 或应用程序提供的、能够保持数据一致性的备份方式,并使数据与相关文件的时间点保持一致。检查命令有时也会新建一个空 DB,因此在确认“完整性检查成功”之前,先确认恢复出的文件确实存在。
如果要启动认证基础设施等进行验证,应隔离网络,防止具有相同标识信息的副本与生产环境通信。使用容器或命名空间时,先检查隔离确实有效,再执行挂载或启动。还要确认用于准备验证用/run的处理不会覆盖生产主机的/run。
4. 不只保存配置,还要记录“原有运行状态”
除了备份配置文件,还要记录以下状态。备份位置应设为只有管理员可读取,并按每次作业分别创建目录,以免覆盖已有记录。
| 保存对象 | 之后核对的内容 |
|---|---|
| OS 和软件包 | 版本、当前运行内核、已安装软件包、APT 软件源和 hold 状态 |
| 网络和 SSH | Netplan、SSH 配置、VPN 配置、防火墙管理方式 |
| 服务 | unit 和 drop-in、启动时的启用或禁用状态、当前运行状态 |
| 定时任务 | timer、cron、备份任务的启用或禁用状态及下次运行时间 |
| 应用程序 | 配置、数据位置、容器配置、外部依赖 |
以下是在使用 Netplan 和 systemd 的 Ubuntu 中备份状态的示例。确认目标目录存在后,先用sudo -i进入 root shell,再执行。mktemp创建的新目录仅允许 root 访问,不会覆盖之前的记录。
umask 077
record_dir=$(mktemp -d /root/ubuntu-upgrade.XXXXXX) || exit 1
cp -a /etc/netplan /etc/ssh /etc/systemd/system "$record_dir/" || exit 1
apt-mark showhold > "$record_dir/apt-hold.txt"
systemctl list-unit-files > "$record_dir/unit-files.txt"
systemctl list-units --type=service --all > "$record_dir/services.txt"
systemctl list-timers --all > "$record_dir/timers.txt"
cat /proc/sys/kernel/random/boot_id > "$record_dir/boot-id.txt"
此示例不包括应用程序专属配置和外部存储中的数据。请添加上表整理出的目标,并在作业记录中注明备份位置。
以下是用于检查的命令示例。包含主机名、连接目标或配置内容的输出不要公开,应作为作业记录保存。
cat /etc/os-release
uname -r
cat /proc/sys/kernel/random/boot_id
apt-mark showhold
systemctl list-timers --all
systemctl --failed
sudo sshd -t
sshd -t用于检查 SSH 配置语法。即使成功,也无法确认外部可以连接。Netplan 也应分别检查语法、生成结果和实际通信状况。
如果为了更新而停止 timer 或临时修改 hold,应记录原有状态及理由。作业后不应一律“全部启用”,否则连有意停止的任务也会运行。恢复配置时,也不要把整个/etc替换为旧状态,而应逐项比对这次修改的差异。
5. 把无人使用的瞬间转化为可安全停机的条件
对于只想在没有用户使用时停止的服务,除了用户数或连接数为 0,还要确认观测范围和时间。仅查看入口代理,不能保证其后端服务器或正在执行的作业也处于无人状态。
先列出用于判断的所有对象,并获取每个对象的最新值。若获取失败、数据缺失或过旧,或者存在未纳入监控的服务器,则不允许停机。“没有值”不能转换为 0,否则监控故障时也会触发停机。
例如,对于通常每隔几秒更新一次的监控,可设置“观测时间和原始数据更新时间均在 15 秒以内”的条件。15 秒只是设计示例,应根据实际更新间隔设定,并确认时钟偏差。如果只需根据人数判断,则不需要采集用户名,也不需要定期向控制台发送列出用户的命令。
停机前,按以下顺序操作。
- 确认所有目标的用户数和处理数均为 0,且没有相冲突的维护作业。
- 在应用程序或负载均衡器上停止接收新请求。采用可等待现有处理正常完成的方式。
- 使用停止接收后生成的新值,再次确认所有目标均为 0。
- 请求正常终止,并确认进程退出且数据保存完毕。
- 完成更新和重启后的功能检查后,再恢复接收请求。
如果停止接收后发现有用户,不要继续停机,而应按预先确定的等待或恢复接收流程处理。不要重复使用之前得到的 0。
如果通过防火墙控制,应检查新连接和现有连接的处理方式、IPv4 和 IPv6、TCP 和 UDP。UDP 的连接处理方式因应用程序而异,因此也应考虑使用应用程序的维护模式。保留管理用 SSH、VPN 和内部通信,并确认重启期间仍保持停止接收状态。使用专用的临时规则,以便恢复时只需移除该规则。
区分“请求正常终止”和“正常终止已完成”
使用systemctl stop时,先确认目标 unit 的ExecStop、停止宽限时间和强制结束设置。如果ExecStop只是发送退出请求便返回,剩余进程可能会被 systemd 终止。应依据systemd 规范,将等待正常结束的处理也包含在内。
对于通过控制台输入来正常结束的服务,正确的命令还必须以带换行的形式送达目标进程。在 unit 中的命令行里,shell 的$()或管道不一定能自动使用。将所需处理封装成小脚本,并加入避免误认目标进程的检查以及等待退出的处理。超时后不要强制结束并继续更新,而应调查无法正常停止的原因。
6. 常规更新要分开执行索引获取、计划检查和应用
完成恢复验证和停机准备后,先获取软件包索引。不要在部分软件源获取失败、仍使用旧索引的情况下继续操作。
# この段階ではパッケージを更新しない
sudo apt-get update -o APT::Update::Error-Mode=any &&
sudo apt-get -s --no-remove dist-upgrade
检查模拟运行的退出码,以及计划更新、新增、删除的内容。--no-remove是需要删除软件包时中止的保护条件。内核等软件包可能需要新增软件包,因此不能把“新增 0”设为常规更新的通用条件。根据APT 规范,模拟过程中的状态并非固定不变。执行前还要再次确认没有其他 APT 任务正在运行,并检查计划是否发生变化。
计划没有问题,且已确认目标服务停止后,就可以应用更新。对于使用 needrestart 的环境,可使用以下示例将额外的重启建议设置为列表显示。
# 通常更新の予定を確認し、必要なサービスを正常停止した後に実行する
sudo env NEEDRESTART_MODE=l apt-get --no-remove dist-upgrade
NEEDRESTART_MODE=l指定needrestart 的列表显示模式。这并不意味着禁止软件包自身配置处理所触发的所有服务重启。应在具备恢复通道的维护窗口中执行,并考虑对 SSH 和 VPN 的影响。不要添加未经检查的-y,也不要指定统一替换所有配置文件。
为防范 SSH 断开,请使用 tmux 等管理员会话,以便断开后任务仍可继续,并记录命令的退出结果。若采用自动执行,应在执行前立即检查目标主机、OS 版本、配置比对结果、备份验证和停机状态,并保存各个中间阶段。不能因为连接中断就重复启动同一更新。
如何处理分阶段更新中暂缓的软件包
Ubuntu 的分阶段更新会先向部分用户提供常规更新,如果发现问题则会抑制后续推送。如果常规更新中仍有因分阶段更新而暂缓的软件包,应记录原因。无需仅为了把暂缓数量降到 0 而改为强制应用。Ubuntu 关于分阶段更新的说明
不过,版本升级的准备工作另当别论。Ubuntu 官方步骤建议连同分阶段提供的更新一起更新当前版本。do-release-upgrade的前提条件应遵循当时的官方步骤。版本升级可能需要替换或删除软件包,因此不要直接把上面的常规更新命令当成升级流程。
执行前,使用以下命令确认可提供的升级目标。
sudo do-release-upgrade -c
只有在提示预期的 LTS、当前版本更新和重启、恢复验证以及兼容性检查全部完成后,才在维护窗口中执行sudo do-release-upgrade。如果仅作检查却未提示升级目标,请调查其提供条件。不要通过指定开发版继续操作。出现配置文件更改确认时,查看差异并判断其对连接和认证配置的影响。
7. SSH 无法恢复时,按顺序检查通信和启动
SSH 连接不上时,通过恢复控制台按以下步骤排查。
| 检查阶段 | 检查示例 | 下一步检查 |
|---|---|---|
| OS 是否已启动 | 控制台、systemctl --failed |
紧急模式、失败的 unit、软件包配置中断 |
| 是否有 IP 和路由 | ip address、ip route |
Netplan 配置来源、接口名称、路由变化 |
| SSH 是否在监听 | sshd -t、SSH 的 service 和 socket |
配置错误、实际监听端口 |
| 外部是否可以访问 | 从另一台主机连接 | 防火墙、VPN、云服务端的通信控制 |
使用 journal 检查当前这次启动。通过journalctl -b -u 対象unit确认启动失败或取消的原因,并通过systemctl show 対象unit -p After -p Before -p Requires -p Wants检查依赖关系。
如果连接用 VPN 的启动被取消,除网络配置外,还应怀疑启动顺序。比如,旧 socket unit 等待 VPN,而 VPN 又等待另一个启动阶段,从而形成循环。确认当前使用的监听和通信之后,只修改已不再承担职责的 unit。采用 socket activation 时,等待连接的 service 处于 inactive 也可能是正常状态,因此不能仅凭状态显示判断它不再需要。
cloud-init 重新生成网络配置时
cloud-init 是执行云端初始设置等工作的机制。若设计上由管理员维护现有 Netplan,应确认更新后重新生成配置不会改变现有设置。可在/etc/cloud/cloud.cfg.d/中的管理文件写入以下内容,以禁用网络配置生成。
network:
config: disabled
这是仅禁用 cloud-init 网络配置生成的设置。不要将它一概用于从云元数据获取网络配置的环境。确认配置管理来源,并验证现有 Netplan 的备份和哈希比对、生成结果,以及常规重启后的通信。
8. 认证或启动兼容问题,仅检查适用的配置
以下内容适用于使用相应软件的环境。未安装这些软件的服务器无需添加。
使用 Samba 提供 Windows 域认证时
Samba 的 AD/DC 是提供 Windows 域认证和目录服务的配置。升级到 Ubuntu 26.04 时,应根据官方升级注意事项,在旧 OS 中确认samba-ad-dc是否已安装。
dpkg-query -W -f='${Status}\n' samba-ad-dc
apt-cache policy samba-ad-dc
确认输出为install ok installed。若未安装,请先确认官方软件源和计划新增的内容,然后在旧 OS 上安装。不要把补齐所需软件包与重建域或修改功能级别混在一起。
备份应采用samba-tool domain backup的适当方式,而不是简单复制 DB 文件。恢复验证除 DB 外,也应在隔离环境中检查目录响应。使用 Samba 4.23 测试时,曾有即使更改 DB 和 PID 保存位置,也因缺少内部套接字用的/run/samba/nmbd而无法启动的情况。将持久化数据和运行时目录分开检查,有助于区分备份损坏与验证环境配置不足。
使用 SSSD 与外部认证基础设施集成时
SSSD 是将 Linux 连接到 AD 或 LDAP 等用户信息和认证基础设施的机制。SSSD 2.10 已移除config_file_version。如果旧配置仍存在,请先保留原文件的所有者和权限,再进行修改,并使用sudo sssctl config-check检查。
还要注意启动方式。由 SSSD 本体的 monitor 启动的 responder,可能与由 systemd socket 启动的同一 responder 发生冲突。responder 是负责用户信息查询和认证等工作的进程。请对照所安装版本的配置规范和日志,仅调整发生冲突的对象。
修正后,检查用户信息获取、所需的认证处理,以及域的 Online 状态。如果是 AD 集成,现有 machine key 的adcli testjoin也属于检查项目。在重新签发密钥或重新加入域之前,先排查配置和启动方式问题。
更新中断、软件包或启动文件不完整时
首先使用sudo dpkg --audit和sudo apt-get check检查未配置的软件包和依赖关系。若另一个 APT 或 dpkg 操作仍在进行,不要重复启动。也不要删除锁文件后强行操作。
确认操作已结束,且确实需要继续配置未配置软件包后,使用sudo dpkg --configure -a恢复配置。确认其退出结果后再继续;如果软件源或依赖问题仍然存在,应先解决。
即使已安装新内核,如果缺少启动所需的 initrd,也无法正常启动。检查/boot容量、已安装内核以及相应的启动文件。创建新 initrd 的update-initramfs -c -k 対象バージョン与更新现有 initrd 的-u用途不同。update-initramfs 规范
修复目标内核应从已安装列表中选择。uname -r显示的是当前正在运行的内核,因此可能指向更新前的旧版本。
无法正常启动而需要使用临时 root 恢复 shell 时,由于操作可能绕过认证,应确认已获管理员许可并遵循操作流程。先以只读方式检查,再仅执行必要的更改。恢复临时启动参数或服务启动抑制设置,最后使用常规 systemd 启动验证。仅在恢复 shell 中启动了服务,并不能证明它能自动启动。
9. 对照重启后的完成条件
更新结束后,确认软件包配置处理已完成,再执行常规重启。重启后,将结果与更新前的记录及以下项目进行核对。
| 完成条件 | 检查证据 |
|---|---|
| 能正常启动 | boot ID 已变化,且未停留在恢复 shell 或紧急模式 |
| 正在运行预期的 OS 和内核 | /etc/os-release和uname -r;不要只根据已安装列表判断 |
| 软件包状态一致 | dpkg --audit、apt-get check的结果 |
| 所需服务已自动恢复 | service、socket、容器、失败的 unit,以及外部响应 |
| 连接和认证可用 | 从另一台主机测试 SSH、VPN 和所需的认证通道 |
| 临时变更已清理 | 接入、防火墙、timer、hold、unit 和配置差异 |
| 更新后的状态可以恢复 | 对新保存版本进行实际恢复的结果和验证内容 |
功能检查不能只从更新的主机内部进行,还要从接近真实用户使用路径的另一台主机执行。对于 API,除确认正常请求成功外,如果路径需要认证,还要确认未认证请求会按规范被拒绝。仅有 HTTP 200 并不能验证认证边界或应用程序的主要功能。
恢复接收请求后,确认没有残留维护用临时 unit 或规则。对于已启用备份的目标,应重新保存完成状态,并恢复这个新的保存版本进行验证。不要把更新前成功恢复的结果当作更新后备份的证据。若备份原本是有意停用的,则保持原来的停用状态。
在最后的作业记录中,写明变更内容、命令退出结果、恢复过程中新增的操作、已验证范围和仍保留的暂缓项目。如果未测试真实用户登录或主要操作,应将相应项目标记为未确认。还应分别记录成功取出部分备份内容,以及能够在另一环境恢复整个服务这两种情况。
更新作业流程
从恢复准备到更新后的恢复验证
只有各阶段检查通过后才进入下一阶段。若失败,记录当时的状态和已执行的操作。
验证恢复并备份配置
取出所需数据,并确保连接通道和变更前的配置可用。
控制接入并更新
重新确认使用情况,正常停止服务并应用计划中的更新。
重启并验证运行状态
检查外部连接、自动启动、恢复原有配置以及新的备份。