
在 Debian 12(bookworm)服务器上执行 apt-get update,输出中反复出现如下报错:
Get:7 https://packages.microsoft.com/debian/12/prod bookworm InRelease [3618 B]
Err:7 https://packages.microsoft.com/debian/12/prod bookworm InRelease
The following signatures couldn't be verified because the public key is not available:
NO_PUBKEY EB3E94ADBE1229CF
Reading package lists...
W: GPG error: https://packages.microsoft.com/debian/12/prod bookworm InRelease:
The following signatures couldn't be verified because the public key is not available:
NO_PUBKEY EB3E94ADBE1229CF
E: The repository 'https://packages.microsoft.com/debian/12/prod bookworm InRelease' is not signed.阿里云 Debian 源、docker-ce 源、zabbix 源全部正常,唯独微软的源报错。
更迷惑的是,某些一键安装脚本(例如宝塔面板安装脚本)会给出这样的提示:
apt-get update 未成功(可能 apt 锁被占用或源异常),等待锁并重试 1/3 ...
检查 apt/dpkg 锁状态...于是很容易误判成「apt 锁被占用」或者「镜像源挂了」,从而在错误的方向上折腾半天。
结论先给:这个报错跟 apt 锁没有任何关系,纯粹是微软源的 GPG 公钥没被 apt 正确加载。
项目 | 内容 |
|---|---|
操作系统 | Debian 12 (bookworm) |
架构 | amd64 |
相关源文件 |
|
报错密钥 ID |
|
出问题的源内容:
$ cat /etc/apt/sources.list.d/mssql-release.list
deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm mainsigned-by 指向的 keyring 文件不存在源条目里用 signed-by=/usr/share/keyrings/microsoft-prod.gpg 显式指定了校验签名要用的公钥文件。检查该文件:
$ ls -l /usr/share/keyrings/microsoft-prod.gpg
ls: cannot access '/usr/share/keyrings/microsoft-prod.gpg': No such file or directory文件压根不存在,所以 apt 无从校验,只能报 NO_PUBKEY。
继续查全局密钥:
$ apt-key list | grep -i -A3 microsoft
pub rsa2048 2015-10-28 [SC]
BC52 8686 B50D 79E3 39D3 721C EB3E 94AD BE12 29CF
uid [ unknown] Microsoft (Release signing) <gpgsecurity@microsoft.com>指纹尾号正是 EB3E94ADBE1229CF,说明公钥确实被导入过——但它是被导入到旧的 /etc/apt/trusted.gpg(apt-key 管理的全局密钥环)里的。
从 Debian 11 开始弃用 apt-key,Debian 12 更是不再信任 trusted.gpg 这种全局、无差别信任的旧机制。而源条目里又用 signed-by 指定了一个具体的 keyring 文件,apt 就只认 signed-by 指向的那个文件,压根不会去全局密钥环里找。
于是就出现了这个经典现象:密钥存在,但 apt 说找不到。
apt/dpkg 锁被占用时的典型报错是这样的:
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 12345 (apt-get)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?而本次报错从头到尾都是 GPG error / NO_PUBKEY / is not signed,属于签名校验阶段的错误,跟锁没有任何交集。脚本里那句"可能 apt 锁被占用或源异常"只是一个笼统的兜底提示,不要当真。
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc -o /tmp/ms.asc可以确认拿到的是正常的 ASCII armored 公钥:
$ head -3 /tmp/ms.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BSN Pgp v1.1.0.0signed-by 的 .gpg 文件必须是二进制格式,不能直接放 .asc 文本,需要 gpg --dearmor 转换:
gpg --dearmor < /tmp/ms.asc > /usr/share/keyrings/microsoft-prod.gpg验证结果:
$ ls -l /usr/share/keyrings/microsoft-prod.gpg
-rw-r--r-- 1 root root 640 Oct 22 09:43 /usr/share/keyrings/microsoft-prod.gpg
$ gpg --show-keys /usr/share/keyrings/microsoft-prod.gpg
uid Microsoft (Release signing) <gpgsecurity@microsoft.com>文件 640 字节,密钥主体正确。
如果没有
gpg命令,先装一下:apt-get install -y gnupg。 也可以不落地临时文件,一行搞定:curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
apt-get update输出(节选):
Hit:1 http://mirrors.aliyun.com/docker-ce/linux/debian bookworm InRelease
Hit:2 https://mirrors.aliyun.com/debian bookworm InRelease
Hit:3 https://mirrors.aliyun.com/debian-security bookworm-security InRelease
Hit:4 https://mirrors.aliyun.com/debian bookworm-updates InRelease
Hit:5 https://mirrors.aliyun.com/debian bookworm-backports InRelease
Hit:6 https://repo.zabbix.com/zabbix-tools/debian-ubuntu bookworm InRelease
Get:7 https://packages.microsoft.com/debian/12/prod bookworm InRelease [3618 B]
Hit:8 https://repo.zabbix.com/zabbix/7.0/debian bookworm InRelease
Get:9 https://packages.microsoft.com/debian/12/prod bookworm/main all Packages [576 B]
Get:10 https://packages.microsoft.com/debian/12/prod bookworm/main amd64 Packages [554 kB]
Get:11 https://packages.microsoft.com/debian/12/prod bookworm/main armhf Packages [20.6 kB]
Get:12 https://packages.microsoft.com/debian/12/prod bookworm/main arm64 Packages [422 kB]
Fetched 997 kB in 3s (315 kB/s)
Reading package lists...微软源的 InRelease 和三个架构的 Packages 全部成功拉取,没有任何 GPG 警告或 E: 错误,问题解决。
理解这一点,以后遇到同类问题就能秒判:
机制 | 密钥位置 | 生效范围 | 状态 |
|---|---|---|---|
旧式 |
| 全局信任,对所有仓库生效 | 自 Debian 11 弃用,Debian 12 不推荐/不再生效 |
新式 |
| 仅对引用它的那一条源生效 | Debian 12 推荐做法 |
新版机制的核心思想是 "per-repository trust":每个第三方源自带自己的公钥文件,通过 signed-by 精确绑定。好处是某个源的密钥泄露也不会影响其他源,同时也避免了全局密钥环里塞满各家厂商公钥的混乱局面。
所以在 Debian 12 上,判断一个第三方源是否配置正确的完整检查清单是:
sources.list.d/*.list(或 .sources)里是否有 signed-by=...;signed-by 指向的文件是否真实存在;file 命令应显示 OpenPGP Public Key,而非 ASCII text);NO_PUBKEY 尾号一致。锁问题的报错一定包含 Could not get lock / Unable to acquire the dpkg frontend lock。看到 GPG error、NO_PUBKEY、is not signed 就与锁无关。
apt-key add 一把梭在 Debian 12 上,apt-key add 已经无法解决 signed-by 场景的缺密钥问题,甚至可能连 apt-key 命令都不再被认可。正确做法是往 signed-by 指定的路径放 keyring 文件。
.asc 文件重命名成 .gpg.asc 是 ASCII armored 文本,apt 无法解析,必须 gpg --dearmor 转成二进制。
--allow-unauthenticated 或 --allow-insecure-repositories 绕过这只是把安全校验关掉,等于对所有第三方包放弃完整性验证,生产环境千万别这么干。正确姿势是把公钥配好。
# 1. 定位是哪个源在报错
grep -rn "packages.microsoft.com" /etc/apt/sources.list /etc/apt/sources.list.d/
# 2. 查看该源的 signed-by 路径
cat /etc/apt/sources.list.d/mssql-release.list
# 3. 确认 keyring 文件是否存在、是否二进制
ls -l /usr/share/keyrings/*.gpg
file /usr/share/keyrings/microsoft-prod.gpg
# 4. 查看 keyring 内的密钥主体与指纹
gpg --show-keys /usr/share/keyrings/microsoft-prod.gpg
# 5. 确认报错指纹(16 位尾号)是否匹配
gpg --show-keys /usr/share/keyrings/microsoft-prod.gpg | grep -i -A1 microsoft思路完全一致——把官方公钥下载下来,gpg --dearmor 到 signed-by 指定的路径。
Docker(新版官方推荐)
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
> /etc/apt/sources.list.d/docker.listZabbix
curl -fsSL https://repo.zabbix.com/zabbix-official-repo.key | gpg --dearmor -o /usr/share/keyrings/zabbix.gpgNodeSource
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpgRedis / 其他厂商同理:从官网取 key,dearmor 到 signed-by 路径,再 apt-get update 验证。
signed-by keyring 文件缺失,apt 无法验证签名,因此拒绝该仓库。apt-key 导入的密钥仍在全局环里,造成"密钥已存在"的错觉;安装脚本的"apt 锁被占用"提示进一步带偏排查方向。curl 下载官方 .asc → gpg --dearmor 转成二进制 → 落到 signed-by 指定路径 → apt-get update 验证。apt-key,所有第三方源统一采用 per-repo signed-by 方案;对一键脚本的兜底提示保持怀疑,先看真实报错,再定位真因。遇到 NO_PUBKEY 时记住这条链:报错里的指纹 → 源的 signed-by 路径 → keyring 文件是否存在且为二进制 → 指纹是否匹配。四步走完,基本不会有漏网之鱼。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。