Ubuntu 26.04 升级后修复 Checklist:从系统体检到桌面工作流恢复

作者:Felix (Haro 协作整理)

这篇原本是我从 0 折腾 Debian / GNOME 办公环境时留下的一组零散记录:终端快捷键、KeePass、输入法、Remmina、Vim、主题、字体、远程网络、Dock 等。

这次从 Ubuntu 25.x 升级到 Ubuntu 26.04 后,我又补了一轮更完整的系统修复记录。和全新安装不同,发行版大版本升级后的重点不是“把所有东西装回来”,而是先判断系统是否健康,再逐步恢复第三方源、驱动、桌面工作流、开发工具和关键应用。

所以这篇整理成一份 checklist:以后升级、重装或迁移桌面环境时,可以按顺序打勾,不用每次从聊天记录和 shell history 里考古。

0. 使用原则

  • ☐ 先只读检查,再修改系统。
  • ☐ 先保证启动、网络、包管理、图形桌面和输入法可用。
  • ☐ 第三方源逐个恢复,不要一次性全打开。
  • ☐ 能用发行版官方包验证的,先别急着恢复上游源。
  • ☐ 每个手工 patch 都记录:改了什么、怎么验证、怎么回滚。
  • ☐ 对会影响系统脚本的替换保持克制,例如不要直接替换 /usr/bin/ls

1. 系统只读体检

升级完成后,先确认系统有没有基础损坏。

  • ☐ 确认发行版和内核版本。
  • ☐ 检查 systemd 是否有失败服务。
  • ☐ 检查 dpkg / apt 状态。
  • ☐ 检查磁盘空间。
  • ☐ 看本轮启动中的高优先级错误。
lsb_release -a
uname -a
systemctl --failed
systemctl is-system-running
apt list --upgradable
dpkg --audit
df -h
journalctl -p 3 -b --no-pager
dmesg --level=err,warn

判断时分三类:

  • ☐ 必须马上修:包管理损坏、启动失败、文件系统/磁盘异常、网络不可用。
  • ☐ 可以延后处理:旧内核、残留配置、autoremove 清理项。
  • ☐ 暂时记录即可:部分 ACPI、厂商 WMI、AppArmor audit 这类硬件/固件噪音。

2. APT / Snap / 第三方源收敛

升级后的源是最容易出问题的地方。我的原则是:官方源优先,PPA 和上游源逐个恢复。

  • ☐ 如果系统策略是不使用 Snap,确认 snapd 是否仍被 hold / 禁用。
  • ☐ 检查当前 APT 源列表。
  • ☐ 禁用还停在旧发行版 suite 的第三方源。
  • ☐ PPA 必须确认已经提供当前发行版包。
  • ☐ 图形驱动、ROCm、内核相关源单独处理,不和普通应用混在一起。
apt-mark showhold
apt-cache policy snapd
apt-cache policy
ls /etc/apt/sources.list.d/
sudo apt update
apt list --upgradable

网络慢时可以临时给 APT 指定代理,但公开记录里不要留下真实代理地址。

sudo apt-get \
  -o Acquire::http::Proxy=http://<proxy-host>:<proxy-port> \
  -o Acquire::https::Proxy=http://<proxy-host>:<proxy-port> \
  update

3. GPU / ROCm 先用官方包验证

如果旧 AMDGPU / ROCm 上游源还没有跟上当前 Ubuntu 版本,先保持禁用,用 Ubuntu 官方包做基础验证。

  • ☐ 安装或确认 rocminforocm-smiamd-smi
  • ☐ 确认 amdgpu 内核驱动已加载。
  • ☐ 确认 /dev/kfd/dev/dri/renderD* 权限正常。
  • ☐ 确认当前用户在 rendervideo 等必要组。
  • rocminfo 能识别 GPU agent。
sudo apt install rocminfo rocm-smi amd-smi
rocminfo
amd-smi list

只要官方包能满足验证和日常运行,就不要为了“恢复原状”急着启用旧上游 ROCm 源。

4. 桌面电源策略:TLP 和外设

升级后要确认 TLP 是否仍然生效,以及有没有和 power-profiles-daemon 冲突。

  • tlp.service 处于 active。
  • ☐ 电池充电阈值仍然生效。
  • ☐ USB 串口、USB 网卡这类外设没有被 autosuspend 影响。
  • ☐ 摄像头这类设备优先考虑恢复后重新枚举,而不是永久常醒。
systemctl status tlp
tlp-stat -s -b -u

本地策略可以放在 /etc/tlp.d/*.conf,例如:

START_CHARGE_THRESH_BAT0=0
STOP_CHARGE_THRESH_BAT0=80
USB_DENYLIST="<serial-adapter-vid:pid> <usb-nic-vid:pid>"

5. CJK 字体和桌面显示

升级后如果中文显示成日文字形,通常是 CJK fallback 顺序变了。

  • ☐ 新增本地 fontconfig 规则,让简中字体优先。
  • ☐ 优先 Noto Sans CJK SCNoto Serif CJK SC 等 SC 字体。
  • ☐ 如果系统存在 JP-first 的通用规则,禁用或降低优先级。
  • ☐ 重建字体缓存。
  • ☐ 用具体汉字验证 sans / serif / monospace 的匹配结果。
fc-match 'sans-serif:charset=590d'
fc-match 'serif:charset=590d'
fc-match 'monospace:charset=590d'
fc-cache -f

6. 终端、快捷键和输入法工作流

全新安装时记录过 GNOME Terminal、tmux prefix、Rime / ibus、主题和字体;升级后这些也要重新确认。

  • ☐ GNOME Terminal 快捷键仍然符合习惯。
  • ☐ tmux prefix 没有被终端或输入法吞掉。
  • ☐ 如果改过 XKB,确认系统文件是否被升级覆盖。
  • ☐ Rime / ibus 配置已恢复。
  • ☐ 输入法快捷键和终端快捷键没有冲突。
tmux show -g prefix
xkbcomp "$DISPLAY" - | grep -n '<key-or-type>'

系统级输入链路的改动一定要留备份。升级会覆盖系统 XKB 文件,不记录的话下次还会重新踩坑。

7. 开发环境恢复

开发环境按“源码、插件、运行时”的顺序恢复。

  • ☐ 自编译 Vim / Neovim 重新编译。
  • ☐ YouCompleteMe、Treesitter、LSP 等 native 扩展重新构建。
  • ☐ 插件更新用普通用户执行,不要误进 root 环境。
  • ☐ Python 工具优先用工具自己的 runtime 管理,避免被系统 Python 主版本升级影响。
  • ☐ 常用命令行工具版本确认:rgfdbatdust 等。
cd ~/vim
git pull
make distclean
./configure <original-options>
make -j<N>
sudo make install

uv python list
uv python install <needed-version>

rg --version
fd --version
bat --version
dust --version

搜索工具要配置全局排除,避免误扫 NAS、云盘挂载、SDK、构建目录、聊天缓存和超大依赖目录;但排除不要过宽,常用系统配置目录应该保留可搜索性。

8. ls / ll 这类基础命令不要硬替换

这次遇到过 ll 输出列间距异常、颜色控制序列导致换行混乱的问题,根因来自 uutils ls 的行为变化。

  • ☐ 先确认实际调用的是哪个 ls
  • ☐ 不要直接替换系统 /usr/bin/ls
  • ☐ 如果要用修复版,安装成独立命令。
  • ☐ 只在交互 shell 里 alias 到修复版。
  • ☐ 系统脚本继续使用发行版自带 coreutils。
type -a ls
type -a ll
ls --version

示例 alias:

alias ls=/usr/local/bin/<patched-ls>
alias ll='/usr/local/bin/<patched-ls> -alFh --color=auto'

9. 清理或回落本地残留包

升级后要找出没有当前源来源的本地包,尤其是系统基础包。

  • ☐ 列出 installed,local 包。
  • ☐ 对关键包检查候选版本。
  • ☐ 如果当前 Ubuntu 源已有候选版本,先模拟回落。
  • ☐ 确认只影响目标包后再执行。
  • ☐ 回落后重新检查 dpkg 状态。
apt list --installed | grep 'installed,local'
apt-cache policy <package>
apt-get -s install <package>=<resolute-version> <library-package>=<resolute-version>

sudo apt-get install --allow-downgrades \
  <package>=<resolute-version> \
  <library-package>=<resolute-version>

dpkg --audit

10. 商业应用和桌面启动器

商业 .deb 往往自带运行库和 postinst 脚本。升级后 GUI 打不开,不要只看图标。

  • dpkg -V 检查包文件是否变化。
  • ☐ 查用户级 journal。
  • ☐ 如果涉及 glibc / native runtime,检查 ELF 属性。
  • ☐ vendor 二进制 patch 前先备份。
  • ☐ patch 后确认 GUI 和关键功能可启动。
  • ☐ 接受 dpkg -V 后续报告 checksum 变化,这是手工 patch 的预期结果。
dpkg -V <package>
journalctl --user -b --no-pager | grep -i '<app-name>'
readelf -lW <app-runtime-library> | grep GNU_STACK

sudo cp -a <library>.so <library>.so.backup
sudo patchelf --clear-execstack <library>.so
readelf -lW <library>.so | grep GNU_STACK

如果应用菜单能打开,但桌面图标打不开,检查 .desktop 文件:

ls -l ~/Desktop/<app>.desktop
sed -n '1,80p' ~/Desktop/<app>.desktop
gio info -a metadata::trusted ~/Desktop/<app>.desktop

cp /usr/share/applications/<app>.desktop ~/Desktop/
chmod 0755 ~/Desktop/<app>.desktop
gio set ~/Desktop/<app>.desktop metadata::trusted true

11. 主题、图标和字体

从 0 搭环境时会安装 Nordic、Kora、LXGW、Fira Code 等主题和字体。升级后除了 APT 包,也要检查用户目录里的手工资源。

  • ☐ APT 管理的主题和字体先查 apt-cache policy
  • ☐ 手工安装但不是 git checkout 的资源,从上游 release 更新。
  • ☐ 替换前保留临时回滚备份。
  • ☐ 图标主题更新后刷新 icon cache。
  • ☐ 字体更新后刷新 font cache。
  • ☐ 如果新版不再提供某个字重,不要马上删除旧文件。
ls ~/.local/share/icons
ls ~/.local/share/fonts
ls ~/.themes

gtk-update-icon-cache -f -t ~/.local/share/icons/<icon-theme>
fc-cache -f ~/.local/share/fonts
fc-match '<font-family>'

12. 手动启动脚本要能暴露错误

桌面监控脚本、conky 这类工具如果“点了没反应”,第一步是把错误恢复出来。

  • ☐ 不要长期使用 >/dev/null 2>&1 & 吞掉所有输出。
  • ☐ 启动前检查命令和配置文件是否存在。
  • ☐ 避免重复启动多个实例。
  • ☐ 日志写到 ~/.cache/<tool>.log
  • ☐ 失败时在终端输出最后几行日志。
  • ☐ Wayland / Xwayland 下检查 Xauthority 是否过期。
conky -c ~/.conkyrc >/dev/null 2>&1 &

上面这种写法适合临时安静运行,不适合排错。升级或重登录后,如果遇到:

Invalid MIT-MAGIC-COOKIE-1 key
can't open display: :0

可以让脚本自动选择最新的 Mutter Xwayland auth 文件。

find "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" \
  -maxdepth 1 -type f -name '.mutter-Xwaylandauth.*' \
  -printf '%T@ %p\n' | sort -nr | awk 'NR == 1 {print $2}'

13. GNOME LocalSearch 索引范围

升级或重登录后,GNOME LocalSearch 可能重新索引整个家目录。如果 $HOME 下有 NAS、云盘、SDK、源码树、构建目录和聊天缓存,CPU 会长时间偏高。

  • ☐ 查看 localsearch-3.service 状态。
  • ☐ 查看当前索引范围。
  • ☐ 如果递归索引整个 $HOME,收窄到常规用户目录。
  • ☐ 把 NAS、云盘、SDK、源码树、build、cache、venv、node_modules 加入忽略。
  • ☐ 重启用户级服务。
  • ☐ 如旧索引异常,再删除本机索引缓存后重建。
systemctl --user status localsearch-3.service
localsearch status
localsearch index
gsettings get org.freedesktop.Tracker3.Miner.Files index-recursive-directories
gsettings get org.freedesktop.Tracker3.Miner.Files ignored-directories

gsettings set org.freedesktop.Tracker3.Miner.Files index-recursive-directories \
  "['&DESKTOP', '&DOCUMENTS', '&DOWNLOAD', '&MUSIC', '&PICTURES', '&VIDEOS']"

systemctl --user restart localsearch-3.service

如果需要重建索引:

systemctl --user stop localsearch-3.service
rm -rf ~/.cache/tracker3/files
systemctl --user start localsearch-3.service

这里删除的是本机索引数据库,不是实际文件,也不会删除 NAS 内容。

14. 摄像头和恢复后重新枚举

如果旧版 cheese 不再可用,可以改用当前 GNOME 推荐的摄像头应用,并确认 V4L2 设备状态。

  • ☐ 安装 gnome-snapshotv4l-utils
  • ☐ 检查 USB 摄像头是否存在。
  • ☐ 检查 /dev/video* 格式。
  • ☐ 检查 GNOME 隐私设置是否禁用了摄像头。
  • ☐ suspend/resume 后找不到摄像头时,只重置目标摄像头,不重置整个 USB 控制器。
sudo apt install gnome-snapshot v4l-utils
lsusb
v4l2-ctl --list-devices
v4l2-ctl --list-formats-ext -d /dev/video0
gsettings get org.gnome.desktop.privacy disable-camera

可通过 systemd sleep hook 在恢复后对目标摄像头做一次重新授权 / 重新枚举,同时保持平时 power/control=auto,兼顾省电和稳定。

15. 最后复查

全部处理完后,再跑一轮只读检查。

  • ☐ 没有失败服务,或失败项已有明确解释。
  • ☐ systemd 运行状态可接受。
  • ☐ apt / dpkg 状态干净。
  • ☐ 高优先级 journal 错误已处理或记录。
  • ☐ 防火墙没有挡住预期服务。
  • ☐ NAS / 云盘挂载正常。
  • ☐ DKMS / Secure Boot 没有影响驱动。
  • ☐ 本地 patch 和手工安装包已记录。
  • ☐ 旧内核、残留配置、autoremove 项有后续清理计划。
systemctl --failed
systemctl is-system-running
apt list --upgradable
dpkg --audit
journalctl -p 3 -b --no-pager

16. 每个改动的记录模板

升级后的修复不适合只留在脑子里。每个手工改动都按这个格式记录,后面迁移机器或复盘时会省很多时间。

## YYYY-MM-DD - Change Title

Context:
- 为什么要做。

Actions:
- 做了哪些修改。
- 涉及哪些文件/包。

Verification:
- 用什么命令验证。
- 当前结果是什么。

Rollback:
- 如何撤回。
- 备份在哪里。

这份 checklist 的重点不是追求升级后一次性“全清干净”,而是按风险顺序恢复:先系统健康,再桌面工作流,再开发环境,再关键应用,最后才是低风险清理。