上周给一台Ubuntu 24.04服务器做常规系统更新时,突然在终端里看到这么一行刺眼的警告:
code复制W: https://example.com/ubuntu/dists/noble/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8)
W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/example.list:1 and /etc/apt/sources.list.d/example.list:2
这个报错的核心在于APT包管理器提示密钥存储方式已过时,而更深层的原因是系统升级后对软件源签名验证机制的安全强化。Ubuntu从22.04开始逐步推行新的安全策略,要求所有第三方源必须明确声明签名密钥(Signed-By字段),而传统直接将密钥添加到/etc/apt/trusted.gpg的方式将被淘汰。
关键背景:现代Linux发行版中,软件源的真实性通过GPG密钥验证。过去我们习惯用
apt-key add命令将密钥加入全局信任环,但这种方式存在安全隐患——任何被信任的密钥都可以为任意软件源签名。新的Signed-By机制实现了密钥与软件源的精确绑定。
传统方式(Deprecated):
bash复制wget -O- https://example.com/key.gpg | sudo apt-key add -
这种方式会将密钥存入/etc/apt/trusted.gpg.d/或/etc/apt/trusted.gpg,成为系统全局信任的密钥。存在两个致命缺陷:
新规范要求的方式:
bash复制sudo mkdir -p /usr/share/keyrings
wget -O- https://example.com/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/example-archive-keyring.gpg
然后在sources.list中显式关联:
code复制deb [signed-by=/usr/share/keyrings/example-archive-keyring.gpg] https://example.com/ubuntu noble main
Noble Numbat(24.04版)带来了几项关键变更:
apt-key命令/etc/apt/trusted.gpg.d/下的密钥首先检查系统当前的密钥和源配置:
bash复制# 列出所有已配置的软件源
grep -r '^deb ' /etc/apt/sources.list /etc/apt/sources.list.d/
# 查看现有GPG密钥环
sudo apt-key list
典型问题源示例(需要修复的格式):
code复制deb https://ppa.launchpadcontent.net/some/ppa/ubuntu noble main
以Docker官方源为例演示完整迁移步骤:
bash复制sudo mkdir -p /usr/share/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
bash复制sudo tee /etc/apt/sources.list.d/docker.list >/dev/null <<EOF
deb [signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu noble stable
EOF
bash复制sudo apt update 2>&1 | grep -i signed-by
对于安装了多个PPA的系统,可以编写自动化处理脚本:
bash复制#!/bin/bash
KEYRING_DIR=/usr/share/keyrings
for ppa in $(grep -hr '^deb ' /etc/apt/sources.list.d/ | grep -v signed-by | awk '{print $2}'); do
repo_name=$(basename $ppa)
key_file="$KEYRING_DIR/${repo_name}-keyring.gpg"
echo "Processing $ppa"
curl -fsSL "${ppa}/ubuntu/gpg" | sudo gpg --dearmor -o "$key_file"
sudo sed -i "s|deb $ppa|deb [signed-by=$key_file] $ppa|" /etc/apt/sources.list.d/*
done
| 错误现象 | 原因分析 | 解决方案 |
|---|---|---|
E: The repository '...' does not have a Release file |
密钥验证通过但源地址错误 | 检查URL中的发行版代号(noble)是否正确 |
W: GPG error: ... NO_PUBKEY ABCDEF123456 |
密钥未正确导入 | 确认gpg --dearmor命令执行成功 |
E: Malformed entry X in list file |
sources.list格式错误 | 检查[]内是否有空格等特殊字符 |
场景1:某些商业软件(如VSCode)提供的安装脚本仍使用旧方法
解决方法:
bash复制# 手动提取密钥并转换
sudo cp /etc/apt/trusted.gpg.d/microsoft.gpg /usr/share/keyrings/
sudo chmod 644 /usr/share/keyrings/microsoft.gpg
场景2:遇到"Clearsigned file isn't valid"错误
这通常是因为密钥服务器响应异常,可尝试:
bash复制sudo gpg --keyserver hkp://keyserver.ubuntu.com:80 --refresh-keys
完成基本修复后,建议进一步优化:
bash复制sudo rm -i /etc/apt/trusted.gpg
sudo rm -ri /etc/apt/trusted.gpg.d/
bash复制sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
bash复制sudo apt update 2>&1 | grep -q "NO_PUBKEY" && echo "存在未验证的源" || echo "所有源已验证"
实际操作中发现,某些边缘案例需要特别注意密钥文件的权限设置——/usr/share/keyrings/下的密钥文件必须设为644权限,否则apt会无法读取。这也是从旧系统升级时容易忽略的细节。