从 Ubuntu 20.04 升级到 24.04,这事儿说起来就是两条命令的事,真正做起来却有不少门道。我最近刚把一台主力开发机和一台业务服务器从 20.04 LTS 一路升到 24.04 LTS,中间踩了五六个坑,也摸清了不少操作细节。这篇文章就把我这次实战的完整过程、命令、取舍逻辑、踩坑记录全部捋一遍,给准备升级的朋友做个参考,尤其适合那些和我一样,系统里已经装了各种开发环境、数据库、第三方软件源的老机器。
先说结论:如果你只是在一台刚装好的 Ubuntu 20.04 上跑几条命令,那升级过程可能二十分钟就结束了。但如果是长期使用的生产机器,升级前不做好排查,多半会在某个环节卡住。这篇文章是按照"升级前准备 → 升级实操 → 收尾清理 → 问题排查"的顺序写的,每一步都有截图级别的描述,你照着做基本能顺利走完。
1. 升级前的灵魂拷问:为什么要升,怎么升才靠谱
1.1 20.04 和 24.04 之间,差了不止一个大版本
Ubuntu 20.04 LTS 发布于 2020 年 4 月,虽然它的标准支持到 2025 年 4 月才结束,但对于很多开发者来说,软件源里的软件版本已经明显跟不上了。比如 20.04 自带的 gcc 是 9.4,Python 是 3.8,OpenSSL 是 1.1.1,而 24.04 LTS 的 gcc 是 13.x,Python 是 3.12,OpenSSL 是 3.0.x。对于需要新特性、新 ABI 的编译任务,旧版本会带来不少麻烦。
这里我需要先纠正一个非常常见的误区:do-release-upgrade 只支持相邻版本升级。也就是说,从 20.04 不能直接跳到 24.04,必须先升级到 22.04 LTS,再从 22.04 升到 24.04。这个规则是 Ubuntu 官方设定的,属于稳妥路线,每跳一级都会重新处理软件包依赖关系,不至于一次性换代导致依赖大面积炸掉。
1.2 两条路线怎么选:在线升级还是重装系统
升级方案其实只有两条主流路线:一是用 do-release-upgrade 在线升级,二是备份数据后重装系统。我个人建议,除非你的机器上就是纯跑一两个服务,否则优先选择在线升级。原因是重装意味着重新配置所有环境,SSH 密钥、计划任务、用户权限、SELinux/AppArmor 策略、服务自启等等,这些隐藏配置的迁移成本远比你想象得高。
那什么时候建议重装?如果当前系统已经被改得很乱,比如手动编译安装了大量的软件、第三方源装了几十个、依赖关系已经出现破损,这种情况下在线升级反而容易二次踩雷。你可以先跑一个 sudo apt update && sudo apt full-upgrade,如果系统能顺利完成整体更新,说明依赖关系还算健康,在线升级是可行的。
1.3 明确升级目标:这次到底要解决什么问题
我在升级前专门列了一个检查清单:系统里有哪些自定义源、哪些服务必须保持版本兼容、哪些内核模块和驱动可能受影响。这份清单不需要多复杂,但能让你在升级过程中遇到问题时有迹可循。比如我自己就有两个硬性要求:Nginx 和 PostgreSQL 的数据不能丢,开发用的 gcc 工具链必须切换到新版本。把目标写下来,后面每一步都以它们为准,不容易被无关问题带偏。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 升级前的准备工作:把风险降到最低
2.1 备份:永远别把系统安全寄托在运气上
升级系统之前,备份这一步绝对不能省。Ubuntu 的在线升级机制已经很成熟了,但它本质上是海量软件包的替换过程,任何一个源的问题、网络中断、断电都可能导致系统进入半升级状态。所以我的习惯是"三层备份":
第一层:重要数据目录单独打包。比如 /home、/etc、数据库的数据目录、网站的 web 根目录。可以用 tar 打包,也可以直接用 rsync 同步到另一台机器或移动硬盘上。我常用的是:
bash复制sudo rsync -avz --progress /home/ /media/backup_disk/home_backup/
sudo tar -czf /media/backup_disk/etc_backup.tar.gz /etc/
第二层:数据库逻辑备份。PostgreSQL 用 pg_dumpall,MySQL 用 mysqldump。这个一定要在升级前做,升级过程中数据库软件会被替换,如果数据文件和软件版本不匹配,恢复起来非常痛苦。
第三层:如果你用的是虚拟机,建议直接打一个快照。这是最省心也最保险的方式。升级失败后,回滚快照等于什么都没发生。物理机的话,可以考虑用 Clonezilla 做整个磁盘镜像,时间略长,但胜在彻底。
2.2 软件源与第三方源排查:升级前最容易被忽略的环节
这是我在升级过程中遇到最多问题的环节。Ubuntu 的在线升级依赖 /etc/apt/sources.list 以及 /etc/apt/sources.list.d/ 下的所有源文件。系统会从这些源里拉取新版本的软件包,如果某个源已经失效或者指向了不存在的仓库目录,升级过程很可能直接中止或者卡在依赖解析阶段。
排查命令很简单:
bash复制grep -rh "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null | sort -u
列出所有源后,逐条确认哪些是官方源、哪些是 PPA、哪些是第三方软件源。对于 PPA,我强烈建议在升级前把不必要的全部移除。因为 PPA 通常只针对特定 Ubuntu 版本编译,比如 20.04 的 PPA 包放到 22.04 里,很大概率出现依赖不兼容。移除方法有两种:如果你知道是哪个 PPA,可以用 ppa-purge;如果不知道,直接在 sources.list.d 里删除对应的 .list 文件和 .list.save 文件即可。
我自己当时的情况是:系统里残留了一个 20.04 专用的 Graphics Drivers PPA,升级到 22.04 时直接导致图形驱动依赖冲突,最后我只能手动删除并重装驱动。这种问题完全可以提前避免。
2.3 系统状态体检:确保没有"带病"升级
为了保证升级能顺利走完,升级前我会做三件事:
第一,确认系统包管理状态正常。运行 sudo apt update 和 sudo apt full-upgrade,把当前版本的所有软件更新到最新状态。如果更新过程中出现依赖错误或破损包,先修复再升级,否则后面新版本的解析会雪上加霜。修复命令可以试 sudo apt --fix-broken install。
第二,检查磁盘空间。升级至少需要 5GB 左右的空闲空间,实际建议留出 10GB 以上。因为升级过程会下载大量软件包,解压、替换、清理都会临时占用空间。另外,/boot 分区也要留意,很多人的 /boot 是独立分区且只有 500MB 左右,如果旧内核太多,升级时新内核可能因为空间不足写不进去。
bash复制df -h
第三,检查系统架构和应用兼容性。比如 32 位系统、UEFI/Secure Boot 状态、是否使用了非默认内核。这些信息可以在升级前用 uname -a 和 lsblk 查看。如果启用了 Secure Boot,而你要安装的驱动或内核模块没有签名,启动时会被拦下来。
3. 正式升级实操:do-release-upgrade 全流程复盘
3.1 先处理终端会话:别让 SSH 断连毁了升级
升级过程需要持续比较久,短则半小时,长则一个多小时。如果你是通过 SSH 远程操作的,一旦网络波动或 SSH 服务被重启,当前终端会话就会断开,升级进程也可能被挂起。所以我强烈建议,在正式开始升级前,先在服务器上开一个 screen 或 tmux 会话,把所有操作都放在这个会话里执行。
bash复制sudo apt install screen -y
screen -S upgrade
这样即使本地终端关闭、SSH 断开,远程的升级进程依然在运行。过一会儿重新登录后,用 screen -r upgrade 就能回到原来的会话。
3.2 从 20.04 升到 22.04:第一跳是关键
在终端里执行版本检查:
bash复制sudo do-release-upgrade -c
如果提示没有可用的新版本,需要检查一下 /etc/update-manager/release-upgrades 文件里的配置。这个文件是升级策略的核心,里面有三种模式:normal(所有版本都会提醒)、lts(只提醒长期支持版本)、never(从不提醒)。在线升级前一定要确保 Prompt 的值是 lts 或 normal,否则系统不会提示任何新版本。
确认无误后,正式启动升级:
bash复制sudo do-release-upgrade
升级过程大概分几个阶段:解析软件源 → 下载新软件包 → 替换系统组件 → 处理配置差异 → 清理旧包。整个过程会多次询问你如何处理配置文件冲突、是否重启服务、是否删除过时包。配置文件冲突的处理原则是:如果你没改过该系统配置文件,选择 N(保留现版本)可能更省事;如果你希望拿到新版本默认配置,选择 Y。但如果你自行修改过配置,务必先备份旧配置,再考虑是否替换。
服务重启的询问我一般选择"保持现有版本",避免某些正在运行的服务因为动态链接库被替换而出现短暂不可用。等系统完全升级完成后,手动重启一次最稳。
3.3 从 22.04 升到 24.04:第二跳注意新机制
升级到 22.04 并重启后,暂时不要急着装新软件,先确认系统和网络都正常。确认没问题后,重复同样的流程:执行一次 sudo apt update && sudo apt full-upgrade,然后再次运行 sudo do-release-upgrade。
从 22.04 到 24.04 这一跳,最大的变化是安装系统组件时的交互变多了,而且会提示你是否允许移除一些不再维护的旧包。我的建议是:对于"删除不再使用的软件包"这类问题,可以选择"是"。因为这些通常是与新版本完全不兼容的老组件,留着反而可能在后续安装软件时引入依赖冲突。
升级完成后重启,系统就正式进入 24.04 LTS。
3.4 升级期间的交互选项这么选
我在升级过程中遇到了四次主要的交互询问,这里统一展开说:
一是 SSH host key 变更提示。升级 OpenSSH 后,系统会生成新的 host key。如果你通过 SSH 连接这台机器,客户端会提示 host key 不匹配,这是正常现象,属服务器端 key 被替换所致。解决方法是记下新 key,更新本地 known_hosts 即可。
二是配置文件冲突。升级时会对比新旧配置的 hash,如果发现本地配置文件被改动过,就会弹出一个多选项界面。如果你不确定自己的修改是否重要,建议选 N 保留旧版,升级结束后再手动对比两个版本。文件通常会保留为 .ucf-old 或 .dpkg-old,用 diff 对比后发现确实需要新配置,再手动合并就行。
三是"重启服务"的窗口。系统会列出所有正在运行的服务,询问是否需要自动重启。我建议选择 否,等所有包替换完成后统一重启。这样能避免服务在依赖更新到一半的时候被重启,引发不可预期的问题。
四是是否删除过时软件包。推荐选择"是"。如果不删,旧包和新包版本混乱,后续 apt 操作很容易报错。
4. 升级后的系统收尾:别以为看到桌面就完事了
4.1 验证版本与内核:确认升到了想升的地方
重启进入系统后,第一件事是确认版本信息:
bash复制lsb_release -a
uname -a
lsb_release -a 输出的 Codename 应该是 noble(24.04 的代号),uname -a 里的内核版本应该是 6.8 系列。如果内核还是旧版本,说明更新过程中内核包没有正常写入,需要检查 /boot 分区空间和内核安装状态。
4.2 清理残留:旧内核、孤儿包与失效源
升级完成后,系统里通常会残留大量旧内核和孤儿包。旧内核不仅占用 /boot 空间,还可能在 grub 菜单里制造超长列表。查看当前已安装的内核:
bash复制dpkg --list | grep linux-image
保留当前正在使用的内核,以及上一个版本的备用内核,其余全部清除。例如:
bash复制sudo apt purge linux-image-5.15.0-xxx-generic linux-image-5.4.0-xxx-generic
sudo update-grub
清完内核后,再来清理孤儿包:
bash复制sudo apt autoremove --purge
这个命令会把升级过程中不再被依赖的所有旧库和旧工具一并移除。注意,执行前可以先用 sudo apt autoremove --dry-run 预览一下会删掉哪些包,确认没有你想留下的软件。
还要检查一下第三方的源文件是否全部失效。之前删掉的那些 PPA,如果还留着对应文件,apt update 时会提示 404 错误。手动把 /etc/apt/sources.list.d/ 下失效的 .list 文件移走或删除即可。
4.3 常用软件环境适配:gcc、Python、Docker 都要过一遍
升级后最大的"隐性成本"是开发环境的适配。以 gcc 为例,20.04 默认的 gcc 是 9.4,24.04 默认是 13.2。如果升级后你执行 gcc --version 发现版本没变,不要慌,大概率是 PATH 里的软链接还指向旧版本。查看 /usr/bin/gcc 的符号链接指向,并用 update-alternatives 重新配置:
bash复制ls -l /usr/bin/gcc*
sudo update-alternatives --config gcc
如果 update-alternatives 里没有对应选项,可以手动添加:
bash复制sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 60
Python 也类似。24.04 自带的 /usr/bin/python3 指向 3.12,但很多手动安装的工具还依赖旧版 Python 路径。建议升级后统一检查一遍 /usr/local/bin 下的可执行文件,确认它们的 shebang 是否还指向 /usr/bin/python3,必要时用 python3 -m venv 重建虚拟环境。
Docker 用户需要额外留意。Docker 的仓库通常会对每个 Ubuntu 版本单独维护,升级后原来的 /etc/apt/sources.list.d/docker.list 可能不再匹配。建议重新添加对应版本的 Docker 源,然后 sudo apt update && sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io。
4.4 网络、桌面与启动项检查
网络配置在 Ubuntu 24.04 里依然是 Netplan 管理。升级后检查网卡配置是否生效,尤其是如果有静态 IP、双网卡或网桥配置的服务器:
bash复制ip a
sudo netplan apply
如果升级后网络不通,多半是 Netplan 配置文件名或语法发生了变化,对比一下 /etc/netplan/ 目录下的 YAML 文件是否还适用。注意,24.04 中渲染器默认可能是 networkd 或 NetworkManager,需要和你的桌面或服务器场景匹配。
桌面用户还要检查一下显卡驱动。升级后 Nvidia 驱动经常失效,表现为 nvidia-smi 报错或桌面直接进不去。这时需要用 ubuntu-drivers devices 重新检测,然后安装推荐的驱动版本。升级过程中如果 Secure Boot 已开启,安装驱动后还可能需要录入 MOK 密钥,这一步不能跳过。
5. 实战中踩过的坑与排查记录
5.1 SSH 在升级过程中突然断开
即使我用了 screen,还是遇到了连接中断。原因是升级时 OpenSSH 服务器被更新,sshd 服务重启会导致现有连接断开。不过有 screen 在手,重新 SSH 登录后执行 screen -r upgrade,升级进程还在跑,完全不受影响。
如果你没有用 screen,又不幸断开了连接,还能不能救?登录后先看有没有升级进程在跑:
bash复制ps aux | grep -E "do-release|dist-upgrade|apt" | grep -v grep
如果有,可以等它跑完,再用 sudo dpkg --configure -a 收尾。如果进程已经没了,多半是升级被中断了,得重新执行 sudo do-release-upgrade,它会基于当前状态继续,而不是从头开始。
5.2 第三方源导致依赖关系崩了
这个坑几乎每个升级的人都遇到过。我在从 20.04 升 22.04 时就因为一个旧的 NVIDIA PPA,导致 libnvidia-common 和系统自带版本冲突。处理方法是:先禁用或删除 PPA,然后执行:
bash复制sudo apt update
sudo apt --fix-broken install
sudo dpkg --configure -a
再重新执行 do-release-upgrade。如果你在升级过程中遇到依赖冲突,不要用 apt remove 去乱删系统包,先想想是不是某个第三方源在作祟。一个非常实用的排查方式是看报错信息里出现频率最高的包名,搜索它属于哪个源,再决定是保留源还是移除源。
5.3 升级后 gcc 还是旧版本?原因和解决办法
这个问题这次也有网友在问,我这次实机也踩了。升级后 gcc --version 输出 9.4,但 /usr/bin/gcc-13 确实存在。问题出在 /usr/bin/gcc 软链接还指向 9.4。解法就是前面提到的 update-alternatives。另外,如果你用的是某些脚本或 Makefile,里面硬编码了 gcc-9,那就需要手动调整了,升级后旧的 gcc-9 包可能已经被 purge,某些头文件路径也会变。
5.4 Python 环境报错与虚拟环境重建
升级到 24.04 后,原来使用 Python 3.8 创建的虚拟环境可能会直接失效,报错信息类似 No module named 'apt_pkg' 或解释器路径不存在。这个问题的根源是虚拟环境里的解释器路径还指向 /usr/bin/python3.8,而升级后系统中可能只剩 /usr/bin/python3.12。解决方法是删除旧虚拟环境,基于新解释器重建,然后重新安装依赖:
bash复制rm -rf myenv
python3 -m venv myenv
source myenv/bin/activate
pip install -r requirements.txt
如果你有大量依赖,建议先把 requirements.txt 和 pip freeze 结果备份出来。
5.5 Nvidia 驱动在升级后失效
从 20.04 一路升到 24.04,Nvidia 驱动基本是必出问题的环节。新内核更新后,旧版 DKMS 模块没能自动重新编译,导致图形界面无法启动。解决办法是进入 recovery mode 或 SSH,执行:
bash复制sudo apt purge nvidia-*
sudo ubuntu-drivers autoinstall
sudo reboot
过程中如果卡在 Secure Boot 的 MOK 管理界面,需要先设置密码,重启后再录入密钥,否则驱动模块不会加载。
5.6 升级后 apt 操作报 "404 Not Found"
这类问题一般发生在升级后的第一次 apt update。根源是 sources.list 中还有旧版本仓库地址,比如 focal 的源,而当前版本是 noble。把旧版本代号替换成新版本代号就行,或者干脆换成镜像源配置。这里也提醒一下,如果你之前使用的是国内镜像源,升级前最好先切回官方源,升级完成后想换再换回来。某些镜像源对版本过渡的同步可能不及时,会导致升级过程中解析新版本失败。
结尾:一点个人实操体会
完整升级完两台机器后,我最大的体会是:Ubuntu 的在线升级机制虽然成熟,但它从来没有承诺你"不会出问题",只是承诺你"出问题之后还有机会修"。真正让升级过程变顺利的,从来不是运气,而是升级前敢花时间备份、敢清理第三方源、敢把系统状态检查清楚,升级中敢用 screen 兜底、敢在交互选项上做对判断。这几件事每件看起来都不起眼,但连在一起,就是一次几乎无痛的版本跨越。如果你的机器上还跑着别人负责的服务,升级前一定提前通知好窗口,升级后也别急着展示新版本号,先跑一圈业务测试再宣布“完成”。这就是我这次 20.04 升 24.04 的全部经验,希望能帮你有惊无险地走完这一趟。
