Insights / 技术解读

更新正在运行的 Ubuntu:事前准备、连接恢复与重启后检查

以从 Ubuntu 24.04 升级到 26.04 以及常规更新为例,具体说明如何实测恢复备份、留存配置、判断无人使用时能否停机、排查 SSH 无法恢复的情况,以及确认完成条件。

  • Ubuntu
  • Linux
  • 备份
  • 运维
更新正在运行的 Ubuntu:事前准备、连接恢复与重启后检查
本文目录
  1. 选择24.04到26.04迁移还是常规更新
  2. 1. 确定更新类型和操作范围
  3. 2. 确保 SSH 断开后仍有其他操作通道
  4. 3. 将备份实际恢复到其他位置
  5. 4. 不只保存配置,还要记录“原有运行状态”
  6. 5. 把无人使用的瞬间转化为可安全停机的条件
  7. 区分“请求正常终止”和“正常终止已完成”
  8. 6. 常规更新要分开执行索引获取、计划检查和应用
  9. 如何处理分阶段更新中暂缓的软件包
  10. 7. SSH 无法恢复时,按顺序检查通信和启动
  11. cloud-init 重新生成网络配置时
  12. 8. 认证或启动兼容问题,仅检查适用的配置
  13. 使用 Samba 提供 Windows 域认证时
  14. 使用 SSSD 与外部认证基础设施集成时
  15. 更新中断、软件包或启动文件不完整时
  16. 9. 对照重启后的完成条件

更新运行中的 Ubuntu 服务器时,除了更新软件包,还必须执行停止服务、并在重启后恢复运维的步骤。SSH 连接中断、认证设置与新版本规范不兼容、无法读取备份等问题,可能会在更新命令结束后才出现。

本文把从 Ubuntu 24.04 升级到 26.04 的 LTS 升级及升级后的常规更新经验,整理成可应用于其他服务器的流程。前提是拥有管理员权限,并且能够安排包含服务停机的维护窗口。首先说明通用准备和操作步骤,后半部分排查连接、认证和启动问题。

选择24.04到26.04迁移还是常规更新

先判断是否需要新一代OS功能,还是当前版本修复已足够。发行版升级需增加外部认证、VPN和DB兼容性检查;常规更新主要核对软件包计划差异和重启影响。两者都应设定中止条件:恢复控制台或实际恢复验证不可用时不开始。

Ubuntu Server:LTS迁移条件与准备

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 秒只是设计示例,应根据实际更新间隔设定,并确认时钟偏差。如果只需根据人数判断,则不需要采集用户名,也不需要定期向控制台发送列出用户的命令。

停机前,按以下顺序操作。

  1. 确认所有目标的用户数和处理数均为 0,且没有相冲突的维护作业。
  2. 在应用程序或负载均衡器上停止接收新请求。采用可等待现有处理正常完成的方式。
  3. 使用停止接收后生成的新值,再次确认所有目标均为 0。
  4. 请求正常终止,并确认进程退出且数据保存完毕。
  5. 完成更新和重启后的功能检查后,再恢复接收请求。

如果停止接收后发现有用户,不要继续停机,而应按预先确定的等待或恢复接收流程处理。不要重复使用之前得到的 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 或规则。对于已启用备份的目标,应重新保存完成状态,并恢复这个新的保存版本进行验证。不要把更新前成功恢复的结果当作更新后备份的证据。若备份原本是有意停用的,则保持原来的停用状态。

在最后的作业记录中,写明变更内容、命令退出结果、恢复过程中新增的操作、已验证范围和仍保留的暂缓项目。如果未测试真实用户登录或主要操作,应将相应项目标记为未确认。还应分别记录成功取出部分备份内容,以及能够在另一环境恢复整个服务这两种情况。

更新作业流程

从恢复准备到更新后的恢复验证

只有各阶段检查通过后才进入下一阶段。若失败,记录当时的状态和已执行的操作。

  1. 验证恢复并备份配置

    取出所需数据,并确保连接通道和变更前的配置可用。

  2. 控制接入并更新

    重新确认使用情况,正常停止服务并应用计划中的更新。

  3. 重启并验证运行状态

    检查外部连接、自动启动、恢复原有配置以及新的备份。