公众号旧文
为什么不盲目在 Linux 上执行 apt upgrade
平时管理 Linux 服务器,软件升级是一件再普通不过的事情。
尤其是 Tailscale 这种网络工具,每隔一段时间就会发布新版本。
我有多台服务器通过 Tailscale 组成私有网络,因此也会定期检查各个节点的软件版本。
今天,我准备将一台日本 VPS 上的 Tailscale 从 1.102.5 升级到 1.104.1。
原本以为只需要几条命令,没想到却遇到了大量 404 Not Found 错误。
好在最后没有盲目修改软件源,也没有升级整个系统,而是通过排查,成功完成了 Tailscale 的单独升级。
这次经历让我进一步认识到:Linux 运维中,知道一条命令怎么执行很重要,但知道它究竟会做什么,更重要。
一、事情从一次普通的软件升级开始
这台服务器的主机名是 jp-sb2,运行 Debian 11,也就是 Bullseye。
我首先执行了:
apt update
命令执行成功,系统提示有 19 个软件包可以升级。
随后,我执行:
apt upgrade tailscale
我原本只是想升级 Tailscale,但 APT 给出的结果却是:
19 upgraded, 1 newly installed
它不但准备升级 Tailscale,还要升级其他系统组件,甚至额外安装一个 Linux 内核。
问题就出在这里:apt upgrade tailscale 并不等于只升级 Tailscale。
apt upgrade 是一个针对系统可升级软件包的操作。
命令末尾写上 tailscale,也不能把它当成严格的单包升级命令。
我当时没有仔细考虑这个区别,直接确认了升级。
结果,安装包下载过程中出现了大量错误:
404 Not Found
E: Unable to fetch some archives
涉及的组件包括 BIND、GRUB、Linux 内核以及其他基础软件包。
有意思的是,Tailscale 的安装包本身已经成功下载,但整个升级任务还是失败了。
二、为什么 apt update 成功,apt upgrade 却失败?
要理解这个问题,首先要区分 APT 的两个操作。
apt update 的作用是更新本地的软件包索引,告诉系统有哪些版本可以安装。
apt upgrade 则会根据这些索引,下载软件包并进行升级。
软件包索引能够正常下载,不代表索引指向的每个安装包都一定存在。
比如,本地索引告诉 APT,某个软件包有一个新版本,并提供了下载路径。
但是当 APT 真正请求这个文件时,服务器却返回了 404。
这通常意味着索引记录与仓库中的实际文件不一致,也可能涉及缓存、镜像同步或仓库调整。
而我的服务器运行的是 Debian 11。
Debian 11 的长期支持已经在 2026 年 8 月 31 日结束。
这次故障又集中出现在 Debian 11 的安全更新仓库,因此仓库维护状态成为了重点排查方向。
不过,需要区分两件事:
Debian 11 已经结束常规 LTS 支持,是明确的生命周期事实;这次所有 404 是否都由仓库生命周期调整直接造成,仅凭终端日志还不能完全确定。
我并没有急着修改软件源,因为眼前真正需要解决的问题,其实只是升级 Tailscale。
三、先搞清楚当前到底安装了什么
我先检查 Tailscale 的版本:
tailscale version
结果是:
1.102.5
这说明此前那次升级并没有成功安装新版本。
接着执行:
apt-cache policy tailscale
输出中最关键的是:
Installed: 1.102.5
Candidate: 1.104.1
这里有两个概念。
Installed 表示当前已经安装的版本。
Candidate 表示根据当前软件源和 APT 策略,系统准备安装的候选版本。
从结果看,Tailscale 官方仓库仍然正常提供 1.104.1。
这就把问题范围缩小了。
我们没有必要因为 Debian 系统仓库里的部分软件包下载失败,就认为 Tailscale 自身也无法升级。
四、真正关键的一步:模拟安装
接下来,我没有马上执行正式升级,而是使用了一个非常实用的参数:
apt-get -s install --only-upgrade tailscale
其中:
-s表示模拟执行,不实际安装软件包。install表示指定操作的软件包。--only-upgrade表示只对已经安装的目标软件包进行升级,而不是把它当成全新软件安装。
注意,–only-upgrade 本身并不保证绝对不会调整依赖,所以仍然需要认真检查模拟结果。
这次 APT 返回:
The following packages will be upgraded:
tailscale
1 upgraded, 0 newly installed,
0 to remove and 18 not upgraded.
看到这里,我才放心了。
因为结果非常清楚:
只升级 Tailscale,不安装新软件包,不删除现有软件包,其余 18 个待升级组件全部保持不变。
模拟执行的价值,就是在真正修改系统之前,让我们知道将要发生什么。
对于承载实际业务的服务器,这个步骤非常值得养成习惯。
五、正式升级,顺利完成
确认模拟结果符合预期后,我执行:
apt-get install --only-upgrade tailscale
这次操作非常顺利:
Unpacking tailscale (1.104.1)
over (1.102.5) ...
Setting up tailscale (1.104.1) ...
没有出现任何 404,也没有触碰其他 18 个待更新的软件包。
随后,我检查了服务状态:
tailscale version
systemctl is-active tailscaled
tailscale status
结果显示:
1.104.1
active
Tailscale 已经成功运行新版本,Tailnet 的其他节点也正常出现在状态列表中。
但我没有就此结束。
因为对于一台通过 Tailscale 提供网络连接的服务器来说,软件升级成功,不等于网络功能一定正常。
六、最后一步:验证网络是否真正恢复正常
我首先测试了这台服务器与另一台日本 VPS 的连接:
tailscale ping 100.64.0.4
返回:
pong from jp-iij (100.64.0.4)
via 156.231.112.139:41641 in 1ms
这条结果说明,jp-sb2 已经能够通过 Tailscale 与 jp-iij 通信,而且使用的是直连方式,不需要经过 DERP 中继。
这次测得的往返延迟只有 1ms。
当然,这只是一次 Tailscale Ping 的结果,不能代表所有网络应用都能稳定保持如此低的延迟。
由于这台服务器还承担 Tailscale Exit Node 的角色,我又检查了内核转发参数:
sysctl net.ipv4.ip_forward
sysctl net.ipv6.conf.all.forwarding
得到:
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
说明 IPv4 和 IPv6 转发都处于开启状态。
再结合 tailscale status 中的 offers exit node,可以确认它仍在广播出口节点能力。
需要注意的是,这些检查证明了基础网络连接、服务状态及转发配置正常,但还不能完全代替真实客户端通过该出口节点访问互联网的端到端测试。
对于此次版本升级,我认为基础验收已经足够。
七、这次经历让我记住了三件事
第一,不能只凭命令名称判断实际执行范围。
我最初使用 apt upgrade tailscale,本意是升级单个软件,却让 APT 准备升级大量系统组件。
以后对需要精确控制变更范围的升级,我会优先使用:
apt-get install --only-upgrade 软件包名
并在执行之前检查依赖变化。
第二,生产服务器值得多做一次模拟。
很多时候,我们并不需要立刻执行修改操作。
先看看当前版本,再检查候选版本,最后通过 -s 模拟安装,可以提前发现很多不必要的风险。
第三,遇到报错不代表必须立即解决所有问题。
这次 Debian 11 还有 18 个软件包没有升级,仓库中也存在需要进一步调查的 404 问题。
但我的目标只是升级 Tailscale。
既然已经找到安全可控的方法完成目标,就没有必要顺手去修改软件源、升级内核,甚至贸然迁移整个操作系统。
当然,Debian 11 已结束常规 LTS 支持,系统迁移和安全维护仍需要后续安排,只是不应该和这次单包升级混为一谈。
写在最后
现在很多人管理服务器,遇到报错的第一反应就是把日志交给 AI,让 AI 直接生成一大段修复命令。
我也经常使用 AI,但我越来越觉得,AI 最有价值的地方,不是替我把所有命令执行完,而是帮助我理解为什么会出问题。
如果只是复制命令,看到成功就结束,下次遇到类似问题,我可能依然不知道从哪里开始。
这次升级虽然只涉及一个 40.5 MB 的软件包,却让我重新理解了 APT 的升级行为、软件仓库索引、模拟安装,以及网络服务升级后的验收过程。
最终,Tailscale 从 1.102.5 成功升级到了 1.104.1,服务器正常运行,节点之间保持直连,其他软件没有被升级。
服务器运维不一定要追求一次解决所有问题。能够准确识别问题,控制变更范围,完成验证后及时收手,本身就是一种能力。
而这些能力,恰恰是在一次次实际排错中慢慢积累起来的。