Ubuntu 16.04升级18.04完整指南:从备份到故障排查
不做任何铺垫直接上干货——ubuntu 16.04升级到18.04这件事我前前后后折腾过好几轮线上服务器、本地开发机都动过手。标题里写了“仅供参考”是因为系统升级这事确实有风险但只要你把流程理顺了它并没有想象中那么吓人。这篇文章就把我实际操作中的完整步骤、踩过的坑、以及处理故障的思路原原本本写出来给正准备动手或者被领导安排干这活的运维朋友一个参考。1. 升级前评估与准备1.1 为什么要用官方升级工具而不是自己改软件源先把最核心的问题说清楚Ubuntu从16.04升级到18.04推荐的路径是用内置的do-release-upgrade命令而不是手动去改/etc/apt/sources.list里的版本代号再执行apt dist-upgrade。这两条路我都试过后者的坑远比你想象的多。手动换源的方式本质上是让APT直接把软件包从一个版本集体迁移到另一个版本。但APT本身的设计并不擅长跨大版本处理依赖关系的剧烈变化很容易出现一套老依赖没被正确替换、新依赖又装不上最后系统处于“半升级”状态。尤其是从16.04到18.04涉及Python、systemd、网络管理等底层的重大更新手动方式很容易翻车。do-release-upgrade是Ubuntu官方封装的升级工具它内部做了几件关键事情读取当前系统版本计算升级路径确定目标版本更新软件源列表到新版本分析依赖关系变化生成需要安装、升级、移除的软件包清单逐个阶段执行并在关键节点提示你确认全程记录日志到/var/log/dist-upgrade/main.log方便排错它也不能保证100%不出问题但至少走的是官方验证过的流程对于大多数默认配置的服务器是最稳妥的选择。1.2 备份永远是第一步别拿“时间紧”当借口可能有人觉得升级不就是为了图省事吗为什么还要花时间备份我见过不止一次升级到一半磁盘写满、或者某个包升级失败导致系统服务起不来的情况。尤其在生产环境任何一个意外都可能变成事故备份的时间成本一定要提前算进去。我的习惯是至少做两层备份第一层数据库和关键数据目录。如果跑着MySQL或者PostgreSQL先做逻辑备份mysqldump -u root -p --all-databases /data/backup/all_databases_$(date %F).sql pg_dumpall -U postgres /data/backup/pg_all_$(date %F).sql第二层对整台机器做快照。云服务器的话直接在控制台做磁盘快照物理机或者虚拟机就用LVM快照。如果你有/etc目录的完整拷贝也已经能解决大部分问题了tar -czf /data/backup/etc_backup_$(date %F).tar.gz /etc备份的存储位置不要放在系统盘上升级过程中下载的新软件包可能就把空间占满了你需要的备份却在同一个磁盘上被顶掉那就尴尬了。最稳妥的方案是备份到独立的数据盘、对象存储或者另一台机器上。1.3 磁盘空间与网络条件检查提前把“硬伤”排掉升级过程需要下载几百MB到1GB以上的新软件包安装完成后还需要腾出空间做备份和临时文件。官方建议至少预留2GB以上的空闲空间但我的实操经验是低于5GB就不要轻举妄动服务器上如果还跑着日志服务瞬间产生大量日志时空间会迅速缩小。检查磁盘空间用一句话就够了df -hT重点看/根分区的使用率还有/var如果独立分区也要单独看。/var/cache/apt/archives目录是软件包下载缓存的位置升级时它会持续增长这点需要心里有数。网络条件是另一个容易被忽略的点。升级需要从Ubuntu官方源或者你配置的镜像源下载大量数据网络中断或者源站点不稳定都会导致进程长时间卡住。建议在执行升级前先测一下连通性ping -c 4 archive.ubuntu.com如果是在境内服务器上操作建议提前把/etc/apt/sources.list里的源切换成你常用的镜像站比如阿里云、清华TUNA等后面会细说。另外记住一点升级期间最好在tmux或者screen会话里跑防止SSH断线导致升级中断这个坑我后面细聊。1.4 梳理当前系统的软件源配置这条非常关键。很多升级失败问题不在Ubuntu本身而是第三方软件源没有适配新版本。先看一下当前的软件源列表cat /etc/apt/sources.list ls /etc/apt/sources.list.d/重点排查两个问题第一有没有第三方源指向特定版本。比如一些数据库厂商、监控组件的源会写成deb http://xxx/ubuntu xenial main版本代号写死了16.04。升级后这些源指向不存在或者不兼容的软件包轻则apt update报404重则干扰整个依赖关系计算。第二有没有你自己加的PPA。ppa:xxx/yyy这类方式在社区软件里很常见但很多PPA并没有同步更新到18.04代号bionic。升级前建议先禁用或者记录下来升级完成后再逐一确认。禁用方式是把/etc/apt/sources.list.d/里对应的.list文件改名加上.bak后缀。2. 核心升级流程详解2.1 先做一次完整的系统更新磨刀不误砍柴工。升级到18.04之前先把16.04本身更新到当前最新状态确保所有软件包都停留在16.04的最新版本之上。这一步的意义在于减少旧版本软件包与新版本之间的版本差降低依赖冲突的概率。依次执行sudo apt update sudo apt upgrade sudo apt dist-upgradeapt upgrade只升级已安装的软件包不处理新增依赖apt dist-upgrade会处理依赖关系变化可能安装新包或移除旧包。两个命令都能执行的情况下建议都跑一遍让系统处于完全干净的最新状态。如果执行过程中出现依赖问题不要跳过先解决掉。常见的apt --fix-broken install可以修复未完成的依赖安装sudo apt --fix-broken install sudo apt autoremoveautoremove会清掉一些升级后不再需要的旧依赖包给后面的升级腾出空间也让环境更干净。这些步骤都完成之后再处理一个重要细节把软件源里的xenial确认一下。如果你用了镜像源此时源应该还是16.04的不要自己手动去改成bionic——升级工具会自动处理。2.2 关键一步执行do-release-upgrade先确保update-manager-core这个包是安装好的因为do-release-upgrade依赖它sudo apt install update-manager-core然后在tmux或者screen里执行sudo do-release-upgrade如果你想要更详细的输出可以加调试参数sudo do-release-upgrade -d-d参数本来是用于开发版升级的但在自定义源或者特殊网络场景下它能打印更多排错信息卡住的时候方便看日志。刚执行时工具会先读取配置文件检查当前版本和可升级版本然后提示你准备开始。它会自动把软件源从16.04切换到18.04之后就是漫长的下载、安装过程。整个过程大概会持续30分钟到数小时不等取决于网络速度和软件包数量。期间会多次进入文字交互界面必须有人盯着按确认。2.3 升级过程中的交互选项到底该怎么选do-release-upgrade运行过程中会出现几个典型的交互提示很多人第一次遇到时会懵不知道该选哪个。我按出现频率逐个说第一个是软件源配置文件变化提示比如Configuration file /etc/apt/sources.list Modified (by you or by a script) since installation. Package distributor has shipped an updated version.这里会问你是保留旧版、安装新版还是看一眼差异再决定。我的经验是选择N保留你现在的版本就可以继续使用你配置好的镜像源。如果误选了其他选项导致源被重置为官方源升级完成后手动改回来就行。第二个是服务重启提示类似Restart services without asking? [y/N]如果你是在生产服务器上操作这里强烈建议选N让它列出需要重启的服务清单你逐个确认。有些服务比如数据库、主业务进程重启时可能造成服务中断必须你自己控制时机。第三个是移除无用软件包提示比如Remove obsolete packages? [y/N]这个根据情况来。如果确认这些包确实不再被依赖选Y可以清理掉回收空间。不确定的话选N升级完成后用apt autoremove再统一清理。整个过程中如果网络中断或者卡很久不动先不要急着杀掉进程等几分钟看看日志再决定。2.4 从16.04到18.04的典型升级时间线我做过的几次升级从执行do-release-upgrade到系统重启大致可以分为这么几个阶段第一阶段更新软件源并获取新版本软件包列表大约3-10分钟第二阶段计算依赖关系生成软件包变更清单大约5-15分钟第三阶段实际下载新软件包这步最慢受带宽影响巨大30分钟到两小时都有可能第四阶段安装和配置软件包涉及大量dpkg操作20-60分钟第五阶段清理旧软件包和缓存10-20分钟最后工具会提示你需要重启系统来加载新内核这时候确认重启即可。3. 升级后的系统恢复与验证3.1 确认系统版本和内核状态重启完成后第一件事确认升级是否真正成功lsb_release -a cat /etc/os-release uname -r正常情况下lsb_release -a应该显示bionic也就是18.04内核版本应该变成4.15系列。如果版本显示还是16.04说明升级过程没有完整走完。另外检查一下当前默认的启动内核dpkg --list | grep linux-image有时旧内核还在启动时默认可能仍加载旧内核。如果确认新内核没问题可以手动清理旧内核释放/boot空间sudo apt --purge autoremove3.2 服务状态全面检查系统重启后最怕的是某个服务没能正常起来。常用的检查命令是systemctl list-units --typeservice --statefailed systemctl list-units --typeservice --staterunning | wc -l如果发现有failed状态的服务逐一看日志systemctl status 服务名 journalctl -u 服务名 -xe --no-pager我遇到过的典型情况是有些老服务写的启动脚本依赖旧版Python环境升级后Python默认版本从3.5变成了3.6导致启动脚本里的路径或者模块加载失败。这种情况要手动修改服务的启动脚本或者虚拟环境路径。另外注意检查SSH服务。如果SSH配置里限制了一些较老的密钥交换算法或主机密钥类型升级后OpenSSH版本提升默认策略可能收紧导致你后续连接时被拒绝。建议升级之后先在当前会话里测试新会话能否正常连接再关闭旧会话。3.3 网络配置变更重点关注netplan这是从16.04升级到18.04最容易踩的坑之一。16.04还使用/etc/network/interfaces这套传统网络配置方式而18.04默认使用netplan配置文件在/etc/netplan/*.yaml。升级工具通常会把旧的配置翻译成netplan格式但翻译结果不一定完全正确。升级后我发现过实际生效的IP和原配置不一致的情况原因就是netplan生成的YAML文件格式有细微出入。先检查当前网络状态ip addr show ip route show再看netplan配置cat /etc/netplan/*.yaml如果发现配置不对可以修改YAML文件然后应用sudo netplan apply如果你是远程连接的服务器改网络配置一定要小心改错了会直接断连。我的习惯是先在另一个会话确认netplan配置语法没问题再用一个定时任务把配置回滚兜底或者干脆在物理控制台上操作。没有控制台通道的情况下宁可不改也不要去赌运气。3.4 清理残留软件包与缓存升级完成后系统里会留有不少不再需要的旧版本软件包和下载缓存。按照这个顺序清理sudo apt update sudo apt dist-upgrade sudo apt autoremove --purge sudo apt autocleanautoclean只清下载缓存中已不可用的软件包clean则是清空所有缓存我认为在升级完成这一步还是保守一点用autoclean就好等你确认系统运行稳定了再来一次clean。还有一个地方容易被忽略/var/lib/dpkg/info目录下可能残留大量旧包的状态信息建议用dpkg --audit检查一下有没有状态异常的包有的话用dpkg --configure -a修复sudo dpkg --configure -a sudo dpkg --audit3.5 第三方软件与业务服务适配如果你的服务器上装了Nginx、MySQL、Redis、Docker等常用组件升级之后不能只停留在“系统正常”这个层面业务层面的组件也必须逐一验证。我自己升级过一台跑着PHP和MySQL的机器16.04默认PHP版本是7.018.04默认是7.2操作系统升级后PHP版本并没有自动跟着切换还是继续使用旧版本的PHP包。这不算错误但如果你想要新版本的特性就需要手动添加第三方的PHP源或者使用工具包管理版本。这里就体现出一个原则千万别在升级过程中混着升级业务组件先让系统稳定再评估要不要更新业务软件。Docker是个特例如果你的Docker版本太老升级到18.04后可能因为内核接口变化导致容器无法启动。建议升级前先记录当前Docker版本升级完成后立即验证容器是否正常启动有问题就去Docker官方源安装兼容版本。4. 常见问题与故障排查实录4.1 SSH会话中断后升级进程还在吗这是远程升级最让人崩溃的问题。SSH一旦断开你跑在普通终端里的do-release-upgrade进程一般会收到挂断信号直接终止下次登录只能看到一个半完成的系统非常被动。所以我前面反复强调必须用tmux或者screen来跑。如果你已经用了tmux断线后重新连接tmux attach -t upgrade就能回到之前的会话进程还在继续跑交互界面也还在。如果没用tmux且升级进程已经被打断不要盲目重新执行升级先看日志sudo tail -n 200 /var/log/dist-upgrade/main.log sudo tail -n 200 /var/log/dist-upgrade/apt.log根据日志判断升级到了哪一步。多数情况下可以重新执行do-release-upgrade它会从断点处继续。如果中途有软件包安装了一半可能要先执行dpkg --configure -a修复后再启动升级。4.2 第三方软件源失效导致update报错升级后执行apt update时我见过大量404错误原因就是旧的第三方源还在指向的是xenial版本。比如E: The repository http://example.com/ubuntu xenial Release no longer has a Release file.处理思路很简单找出这个失效的源文件并处理grep -r xenial /etc/apt/sources.list /etc/apt/sources.list.d/把对应文件改名禁用或把版本代号改成bionic前提是该第三方源确实提供了18.04版本的支持。不确定的源宁可先禁用等确认安全再恢复。4.3 升级后ping得通但SSH连不上有一个比较隐蔽的情况升级后系统本身正常但SSH登录直接被拒绝。大多数时候是/etc/ssh/sshd_config里配置了只允许特定用户或特定认证方式升级过程中OpenSSH软件包更新后默认配置变了。排查步骤systemctl status sshd journalctl -u sshd -xe --no-pager如果是认证方式问题临时在控制台把密码认证打开确认能登录后再把安全策略调回来。登录不了机器时所有其他问题都无从解决所以SSH的检查建议排在第一步。4.4 依赖关系损坏dpkg一直报错升级过程中如果突然断电或者空间不足很可能出现dpkg: error: package xxx is not ready for configuration这类错误。这时需要修复dpkg数据库sudo dpkg --configure -a sudo apt update --fix-missing sudo apt install -f如果某个包反复安装失败可以把它先强制卸载等系统稳定后再重新安装sudo dpkg --remove --force-remove-reinstreq 包名 sudo apt install 包名不到万不得已不要用强制卸载尤其是系统核心组件可能会导致系统无法启动。4.5 升级后显卡或桌面环境异常这个主要影响桌面用户。18.04默认桌面环境做了调整如果你的机器是带GUI的升级后可能出现桌面无法正常加载、分辨率异常、鼠标键盘失灵。我处理过一次比较典型的情况显卡驱动和18.04内核不兼容桌面环境直接无法启动。解决思路是进入TTY终端CtrlAltF3重新安装显卡驱动或者回退到旧内核dpkg --list | grep linux-image sudo apt install linux-image-4.15.0-xxx-generic然后在GRUB启动菜单里选择旧内核进入系统确认后再决定驱动怎么处理。5. 从16.04到18.04的关键变化与升级后的运维习惯5.1 你必须知道的几个重要变更18.04和16.04相比有很多系统层面的变化不提前了解升级后可能连系统怎么管理都找不到北。网络配置前面已经讲过/etc/network/interfaces被netplan取代。如果你习惯在/etc/resolv.conf里手动配置DNS也会发现它变成了一个软链接指向systemd-resolved生成的文件。想要永久修改DNS要去改netplan配置。iptables还是原来的iptables命令但18.04默认使用nftables作为底层内核框架实际默认规则还是通过iptables工具管理。习惯了写iptables规则的朋友建议继续用iptables命令避免直接折腾nftables语法学习成本不低。cron依然可用但18.04引入了systemd-timer作为现代替代方案。我个人的观点是除非你本来就想用systemd-timer的新特性否则不需要特意迁移稳定是第一位的。18.04默认的Python是3.6Python 2还是预装了一些系统脚本在依赖但新代码不要再以Python 2为目标跑了官方早已停止支持Python 2。5.2 升级后推荐你调整的一些运维小习惯升级完成、业务恢复、观察一周没问题系统就算稳定了。这时候建议做几件收尾工作第一更新你的监控指标。如果你用Zabbix、Prometheus这类监控系统检查一下操作系统的采集项。18.04的一些CPU、内存等指标获取方式发生了变化和这套系统版本强相关的监控模板需要同步更新。第二整理一份系统信息清单。内核版本、sshd配置、netplan网络配置、软件源列表、当前运行的服务都记录到一个文档里。下次再遇到问题时这份清单能帮你省掉大量排查时间。第三关闭或者删除不再需要的旧内核。系统升级往往会保留多个内核磁盘小的机器/boot分区容易被占满。定期执行sudo apt --purge autoremove可以安全清理旧内核但建议预留一个刚升级完的系统运行几天再清理确保新内核稳定。第四重新审视安全更新策略。18.04是LTS版本支持周期到2023年但那是标准支持期。实际到了生命周期末尾如果没有及时迁移到20.04或者24.04安全更新会自动停止届时需要考虑下一步升级计划。所以这个时刻就要把下一次升级提前纳入规划了避免再次被版本过期逼到墙角。5.3 升级容易迁移思维更难最后说点个人体会。16.04到18.04这次升级技术难度其实不算高毕竟有官方工具帮你兜底。但它背后反映的问题是长期运行的系统如何持续保持在一个受支持的状态。这需要运维人员对系统的版本生命周期有清晰的认知在版本还在支持期内就规划好升级窗口而不是等支持期过了、安全补丁不更新了才急急忙忙去升级。在我实际接触的团队里很多服务器都停留在老版本上原因各式各样无非是“业务太忙没时间”“感觉现在跑得挺稳的没必要动”“害怕升级出问题”。这些想法能理解但系统版本过旧带来的风险是真实存在的安全漏洞没人补、新软件装不上、硬件驱动不兼容。等到问题集中爆发时升级的难度和风险就会成倍增加。从长远来看建议哪怕没有升级需求也要保持每个LTS版本的生命周期概念。18.04之后的下一次升级你可以考虑直接跳到20.04因为18.04已经过了主流支持期。如果还想继续用18.04那就记得把系统源切到旧的维护源比如old-releases.ubuntu.com才能继续获取安全更新。不过那只是过渡方案而已。再补充一个实用技巧升级完成之后把安装时生成的日志文件保留一段时间不要马上清理。/var/log/dist-upgrade/和/var/log/apt/里的日志对后续排查任何和系统库、软件包相关的问题都很有帮助。我的习惯是保留至少一个完整的升级日志周期等到确认系统没有任何隐藏问题再统一清理。这次升级的经验就分享到这里。整个过程归根到底就是备份充分、准备细致、过程紧盯、事后验证。如果你正准备给自己的服务器做这个升级希望这篇文章能让你少走一些弯路。