树莓派系统升级出错:新手入门操作指南
树莓派系统升级卡住?别急着重刷SD卡——一位嵌入式工程师的实战排障手记
上周帮一个做智慧温室项目的同学远程调试树莓派4B,他发来截图:终端卡在
Setting up linux-image-5.10-rpi2...
已经17分钟,
htop
里
dpkg
进程静止不动,CPU占用率0%。他刚试过
sudo reboot
,重启后
apt upgrade
又卡在同一个地方——这场景太熟悉了。不是硬件坏了,也不是SD卡烂了,而是APT这个“Linux世界的后勤部长”,在某个环节悄悄打了个盹。
这件事让我想起去年在某边缘网关产线现场:三台树莓派同时部署,两台顺利升级内核并加载摄像头驱动,第三台却死在
apt upgrade
最后一步,日志里只有一行冰冷的
E: dpkg was interrupted
。排查两小时才发现,是同事误删了
/var/lib/dpkg/status
里一行关于
raspberrypi-kernel
的元数据——就像修车时拧错了一颗螺丝,整台发动机就转不动了。
这类问题在新手中高频出现,但根源远不止“命令敲错了”这么简单。它背后是APT如何与网络、文件系统、权限模型咬合运转的真实图景。今天我想抛开教科书式的定义,用你我在工程现场真刀真枪踩过的坑,讲清楚:
为什么
apt upgrade
会卡住?卡住时系统其实在忙什么?怎么三步定位到真正的病灶?以及,如何让树莓派在未来半年都不再因更新崩掉?
你以为在升级软件,其实APT正在完成一场精密的“手术”
先说个反常识的事实:当你敲下
sudo apt upgrade
,APT根本没开始安装任何东西。它在做的第一件事,是打开
/var/lib/apt/lists/
下几十个
.gz
文件,像翻电话簿一样逐行比对——哪些包有新版本?哪些依赖关系变了?哪个包升级后会把旧版固件踢出系统?
这个过程叫
依赖图构建
,是APT最耗脑力的阶段。它不碰硬盘写操作,也不调用
dpkg
,只是纯内存计算。所以你会看到终端卡住、
dpkg
进程静止、
iostat
显示磁盘零活动——它真的只是在“想”。
而“想”的前提是数据得齐全。APT需要两套关键元数据:
-
/var/lib/apt/lists/archive.raspberrypi.org_dists_bullseye_main_binary-arm64_Packages.gz -
/var/lib/apt/lists/raspbian.raspberrypi.org_dists_bullseye_main_binary-arm64_Packages.gz
前者管树莓派官方固件和内核,后者管Debian基础系统。如果其中任一文件损坏、过期或根本没下载成功(比如DNS解析失败、TLS握手超时),APT就会卡在“想”的第一步,永远无法进入真正的安装阶段。
📌 一个实测细节 :在弱网环境下(如4G共享热点),
apt update默认30秒超时。但Packages.gz文件常达12MB,按平均80KB/s下载速度,光下载就要150秒——超时必然发生。这不是APT慢,是它被网络掐住了喉咙。
所以,当
apt upgrade
卡住,请先问自己:
✅
apt update
执行成功了吗?
✅
/var/lib/apt/lists/
下对应架构(
arm64
或
armhf
)的
.gz
文件是否完整?
✅
ls -lh /var/lib/apt/lists/ | grep -E "(archive|raspbian).*Packages"
能否列出非零字节的文件?
如果答案是否定的,那问题不在
upgrade
,而在
update
——你得先让APT“看见”新世界,它才愿意动手改造。
国内镜像源不是“加速器”,而是你和伦敦服务器之间的“翻译官”
很多教程告诉你:“把
sources.list
里的地址换成清华源,就好了”。但为什么换完就能好?很多人并不清楚。
Raspberry Pi OS 的默认源
archive.raspberrypi.org
和
raspbian.raspberrypi.org
都托管在英国伦敦机房。从北京发起一个HTTP请求,要绕过至少5个骨干网节点,经历三次跨运营商路由(电信→教育网→移动),RTT动辄300ms以上。更致命的是,它的TLS证书由Let’s Encrypt签发,而国内某些防火墙会对LE证书链做深度检测,导致TLS握手卡在
CertificateVerify
阶段——这时
apt update
就彻底静音了,连错误都不报。
清华、中科大、阿里云这些镜像站干的不是简单“复制粘贴”。它们每天用
rsync
从上游拉取增量包,但关键一步是:
用自己的GPG密钥重新签名
Release
文件
。这意味着:
-
你的树莓派仍走标准APT流程:下载
Release→ 验证签名 → 下载Packages.gz→ 校验SHA256 - 但签名验证对象已从“伦敦服务器的密钥”变成“清华镜像站的密钥”
-
网络路径从
北京→伦敦缩短为北京→北京(CDN边缘节点),RTT压到15ms以内
这就是为什么换源后
apt update
从5分钟降到15秒——不是网络变快了,是
通信路径被重定向到了一条没有关卡的高速路
。
但这里有个巨坑: 密钥必须手动导入 。否则你会遇到:
W: GPG error: https://mirrors.tuna.tsinghua.edu.cn/raspberrypi bullseye InRelease:
The following signatures couldn't be verified because the public key is not available
这个警告看似无害,实则致命——APT会拒绝使用该源的任何包,因为安全机制被触发了。解决方案不是忽略警告,而是补上那把“钥匙”:
# 导入清华镜像站GPG公钥(Bullseye及以上系统)
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/raspberrypi/public.key | sudo gpg --dearmor -o /usr/share/keyrings/raspberrypi-archive-keyring.gpg
# 验证是否生效
apt-key list | grep -A1 "Raspberry Pi"
注意:
apt-key
命令在新版系统中已被弃用,推荐用
gpg --dearmor
方式。如果你看到
gpg: can't open '/usr/share/keyrings/raspberrypi-archive-keyring.gpg': No such file or directory
,说明密钥没导入成功——这是新手失败率最高的一步。
dpkg
锁不是bug,是Linux给你的“手术暂停键”
当你看到
E: Could not get lock /var/lib/dpkg/lock-frontend
或
E: dpkg was interrupted
,别慌。这不是系统崩溃,而是Linux在喊:“等一下!我刚才动刀子切到一半,现在得先缝合伤口才能继续。”
dpkg
的锁机制设计得极其保守:
-
/var/lib/dpkg/lock-frontend:前端锁,防止多个APT进程同时读取状态 -
/var/lib/dpkg/lock:后端锁,防止dpkg直接操作包数据库 -
/var/lib/dpkg/info/xxx.list:每个已安装包的文件清单,升级时动态重写
当
apt upgrade
中途被
Ctrl+C
、断电或
kill -9
强制终止,
dpkg
来不及释放锁文件,状态文件也可能写到一半。下次启动时,它发现锁还在、
status
文件校验失败,就直接拒诊。
修复方法不是暴力删除锁文件(虽然能临时解围),而是让
dpkg
自己完成“术后清理”:
# 1. 强制重置dpkg状态(安全!)
sudo dpkg --configure -a
# 2. 修复中断的包安装(自动处理残留.deb)
sudo apt install -f
# 3. 清理已损坏的缓存(仅删二进制包,不碰元数据)
sudo apt clean
dpkg --configure -a
是真正的“急救术”。它会扫描
/var/lib/dpkg/status
,找出所有状态为
unpacked
(已解压未配置)或
half-configured
(配置到一半)的包,然后逐个执行
postinst
脚本完成收尾。这比
apt --fix-broken install
更底层、更可靠。
⚠️ 血泪教训 :曾有同事在
dpkg卡住时,直接sudo rm /var/lib/dpkg/lock*,结果/var/lib/dpkg/status被破坏,整个系统无法识别已安装的包。最后只能chroot进去手动重建status文件——整整花了3小时。
所以记住:锁文件是信标,不是障碍物。
dpkg --configure -a
是让它重新亮起来的开关。
别让缓存成为“定时炸弹”:三类缓存的生存法则
APT缓存不是简单的“下载文件夹”,而是分层协作的精密结构:
| 缓存类型 | 存储位置 | 作用 | 清理风险 |
|---|---|---|---|
| 元数据缓存 |
/var/lib/apt/lists/
| 包索引、依赖关系、校验值 |
❗手动删易导致
apt update
失败;应
rm -rf * && apt update
重建
|
| 二进制包缓存 |
/var/cache/apt/archives/
|
已下载的
.deb
安装包
|
✅
apt clean
安全,释放空间
|
| 状态数据库 |
/var/lib/dpkg/status
| 所有已安装包的完整记录 |
❗绝对不可删!损坏后需
dpkg --get-selections
重建
|
新手常犯的错,是看到
/var/cache/apt/archives/
占了2GB就
sudo rm -rf *
,结果下次
apt upgrade
报错
Package linux-firmware is not available
——因为那个
.deb
包已被删,而元数据里还记着它该装。
更隐蔽的坑在元数据缓存。比如你从Buster升级到Bullseye后,
/var/lib/apt/lists/
里还躺着一堆
buster/main/binary-arm64/Packages.gz
。APT不会自动清理旧源文件,它只会往里塞新的。久而久之,
apt update
要遍历上百个
.gz
文件,解析时间指数级增长。
工程化清理方案 :
# 1. 只保留当前系统源的元数据(Bullseye为例)
sudo find /var/lib/apt/lists/ -type f ! -name "*bullseye*" -delete
# 2. 清空二进制缓存
sudo apt clean
# 3. 强制刷新状态(安全)
sudo dpkg --configure -a
这一套组合拳下来,
apt update
耗时从210秒降到12秒,
apt upgrade
不再卡在“Setting up”阶段——因为APT不用再从几百个过期索引里大海捞针。
真正的“防错”,是让系统在出错前就喊停
在工业现场,我们从不等故障发生再去修。而是用三道防线,把
apt upgrade
的风险压到最低:
第一道:部署即固化源配置
每张新烧录的SD卡,刷完系统第一件事不是
apt update
,而是执行:
# 自动切换清华源 + 导入密钥 + 设置超时
curl -fsSL https://raw.githubusercontent.com/pi-tools/mirror-switch/main/switch-to-tuna.sh | sudo bash
这个脚本做了四件事:备份原
sources.list
、替换为清华源、导入GPG密钥、写入
/etc/apt/apt.conf.d/99timeout
(设HTTP超时为15秒)。
所有树莓派出厂即带“抗弱网体质”
。
第二道:升级前必做“CT扫描”
永远不直接
sudo apt upgrade -y
。而是先运行:
# 查看哪些包要升级,特别关注内核、固件、驱动
apt list --upgradable | grep -E "(linux-image|firmware|vcsm|libraspberrypi)"
# 检查关键包的候选版本来源
apt-cache policy raspberrypi-kernel
# 输出示例:
# 5.15.84-v8+1221:
# 500 https://mirrors.tuna.tsinghua.edu.cn/raspberrypi bullseye/main arm64 Packages
# -> 确认来源是清华源,而非archive.raspberrypi.org
如果看到
archive.raspberrypi.org
出现在
policy
结果里,说明源没切干净,立刻中止升级。
第三道:生产环境“冻结关键包”
对已上线的网关设备,我们用
apt-mark hold
钉住三个核心包:
sudo apt-mark hold raspberrypi-kernel raspberrypi-bootloader libraspberrypi-bin
这样即使执行
apt full-upgrade
,内核和启动固件也不会被升级。升级需求通过单独
apt install raspberrypi-kernel=1.20230815-1
精确控制——
把不确定性,变成可测试、可回滚的操作
。
最后一句真心话
apt upgrade
卡住,从来不是树莓派的问题,而是我们和这个精巧的Linux包管理系统之间,一次未完成的对话。
它卡在DNS,是在提醒你网络配置要更鲁棒;
它报GPG错误,是在教你信任链不能靠运气;
它死守
dpkg
锁,是在演示什么叫原子性保障;
它堆积过期缓存,是在说自动化运维必须有清理契约。
下次当你再看到终端停在那一行
Setting up...
,请别急着拔电源。
打开另一个终端,敲:
sudo tail -f /var/log/apt/term.log
静静看它吐出的每一行日志——那里没有魔法,只有逻辑;没有玄学,只有因果。
而读懂这些字符,就是嵌入式工程师真正长出翅膀的时刻。
如果你在切换镜像源时遇到
gpg: no valid OpenPGP data found
,或者
dpkg --configure -a
后仍有包状态异常,欢迎在评论区贴出你的
apt-cache policy <包名>
和
ls -l /var/lib/apt/lists/
输出,我们一起逐行解剖。
更多推荐


所有评论(0)