news 2026/10/20 21:27:43

修复Ubuntu 24.04下APT报错:Signed-By缺失的完整排查与解决

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
修复Ubuntu 24.04下APT报错:Signed-By缺失的完整排查与解决

如果你在一台 Ubuntu 24.04 机器上执行apt update,输出里突然出现一行带着sources.list(5)的告警,还明确说某个源缺少Signed-By,第一反应多半是懵的:系统刚更新完,什么都没动过,为什么源配置突然不合法了?这个报错我最近陆续处理了好几遍,表面看是某个源文件写得不够新,本质是 APT 在 24.04 上把安全校验收紧了一圈。这篇文章我就按照“看到报错 -> 定位根因 -> 补上 Signed-By -> 验证修复”的顺序,把整条排查链路完整讲一遍。

1. 报错现场:这条“Signed-By”错误到底出现在哪一步

1.1 我遇到的具体报错形态

先说最容易让人困惑的地方。报错不是出现在安装软件时,而是集中在apt update阶段。正常跑更新时,APT 会逐个读取/etc/apt/sources.list和/etc/apt/sources.list.d/下的源定义,然后去远程仓库拉取索引文件。到了 Ubuntu 24.04,如果某个源定义里没有声明Signed-By,而系统又找不到对应的信任密钥,就会看到类似下面这段输出:

W: https://packages.example.com/ubuntu/dists/noble/InRelease: Signed-By is not set for source 'example_source' (sources.list(5)) E: The repository 'https://packages.example.com/ubuntu noble InRelease' does not have a Release file. N: Updating from such a repository can't be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details.

不同版本和不同仓库的输出措辞会有差异,有的 W 行写在前面,有的 E 行直接把仓库跳过,但核心信息是一致的:APT 想验证这个仓库的 Release 文件签名,却发现你没有在源定义里告诉它该用哪把钥匙。在我处理过的案例里,最典型的情况就是升级前本来正常的第三方源,升级后直接变成了“不能安全更新”的禁用品。

1.2 sources.list(5)里的数字5是什么意思

很多读者第一次看到sources.list(5)会误以为这是某个文件路径或者报错编号,其实这是 Linux 手册页的引用写法。sources.list(5)表示sources.list这份文档位于 man 手册的第 5 节,这一节专门放系统配置文件格式说明。APT 在告警里带上这个标记,是在提醒你:去查man sources.list,它会解释源定义文件应该怎么写。

我自己的排查习惯是,遇到 APT 的源相关报错,先打开手册再动手。24.04 的man sources.list和旧版本很不一样,里面详细解释了两种格式:传统的单行格式deb http://...,以及新的 DEB822 格式。绝大多数人报错,就是因为系统自动迁移之后你的源定义碰巧卡在两种格式之间,字段不全。

1.3 报错不只是烦人,它代表apt的安全防线失效

这条报错不是一个简单的格式问题。APT 的核心安全模型是:软件源索引文件必须经过 GPG 签名,系统要用一把你信任的公钥去验证签名。Signed-By这个字段就是用来指明“验证这个仓库应该用哪个 keyring 文件”。

如果缺失Signed-By,APT 理论上会退回使用全局信任的/etc/apt/trusted.gpg.d/和旧式trusted.gpgkeyring。但是 Ubuntu 24.04 对这套遗留机制的态度已经很明确了:apt-key被标记为弃用,全局信任区不再是无条件的默认信任。于是一个安全防线失效的源,就会被 APT 判定为不可信,宁可跳过也不冒险启用。理解了这一点,你就知道为什么不能简单地用trusted=yes绕过校验一劳永逸。

2. 为什么偏偏在更新系统之后爆发:apt源机制的两层变化

2.1 Ubuntu 24.04的源定义换成了DEB822格式

Ubuntu 22.04 时期,系统开始支持一种新的源定义格式,后缀是.sources,不再是单纯的行文本,而是一种“块状配置”,看起来很像 INI 文件。到了 24.04,新安装的系统默认就是这种写法。典型内容如下:

Types: deb URIs: http://archive.ubuntu.com/ubuntu/ Suites: noble Components: main universe restricted multiverse Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

每个字段一行,语义清晰。URIs是仓库地址,Suites对应发行版代号,Components是组件,Signed-By是密钥环路径。和传统deb http://... noble main相比,这种格式最大的优势就是能把源地址、套件、组件、签名钥匙分开管理,不再挤在一行里靠括号选项区分。

问题也出在这里:当系统升级或者第三方安装脚本自动写入源配置时,如果只写地址和套件,忘记补Signed-By,APT 在 24.04 上会直接把它当成一个没有安全来源的仓库来拒绝。

2.2 从apt-key到独立keyring:Signed-By为什么成了必需品

在旧版本 Ubuntu 上,第三方软件源安装流程通常是:执行apt-key adv --keyserver ... --recv-keys,或者下载公钥后用apt-key add导入。apt-key会把密钥统一放到/etc/apt/trusted.gpg.d/和/etc/apt/trusted.gpg里,所有源都依赖这个全局信任区。

问题在于,全局信任区过于集中。你只是为某个第三方仓库装了一把钥匙,结果这把钥匙拥有了系统里所有源的最高信任级别,一旦钥匙泄露,攻击者可以给任意仓库签名。更新到 24.04 之后,APT 社区明确建议每个源使用独立 keyring,并在源定义里用Signed-By指向它。这样的隔离设计下,第三方源的密钥没有资格验证官方源,官方源的密钥也管不到第三方仓库。

所以现在第三方源的标准做法变成两步:第一步下载公钥并转换为独立的 keyring 文件,第二步在源定义里通过Signed-By指定这个 keyring。跳过任何一步,都可能触发你看到的报错。

2.3 系统升级工具迁移源定义时会丢什么

有人会疑惑:为什么升级之前明明没报错,升级之后就有了?这里有两种常见情况。

第一种,升级工具把旧版/etc/apt/sources.list内容迁移到了新的.sources文件里,但迁移时只保留最基础的字段,没有自动补上Signed-By。旧版靠全局信任区工作,新版只见源定义、见不到钥匙,于是报错。

第二种,升级前你通过第三方脚本添加了软件源,脚本只写了源地址,钥匙用的还是老的apt-key。系统升级之后apt-key被弃用甚至不可用,全局信任区也没有对应 keyring,APT 无法完成签名验证,自然只能跳过。

我遇到过最隐蔽的情况是:第三方源定义在/etc/apt/sources.list.d/里,但对应的 keyring 文件存放在/etc/apt/keyrings/,升级过程中/etc/apt/keyrings/目录没有被迁移或者权限被改,最终整个目录空空如也,源定义里的Signed-By指向了一个不存在的文件。这类问题不仔细查目录根本发现不了。

3. 排查链路:先定位是哪个源、丢的是哪把钥匙

3.1 第一步:把apt update的完整输出存下来看

不要只看屏幕上最后几行,建议把完整输出重定向到日志文件:

sudo apt update 2>&1 | tee /tmp/apt-update.log

然后重点找三类行:W:开头的告警行、E:开头的错误行、以及N:开头的提示行。告警行通常直接告诉你是哪个 URL、哪个源条目出了问题,比如上面例子里的https://packages.example.com/ubuntu/。这一步看起来很简单,但很多人会跳过,结果修了半天都不知道是哪个源在报错。

如果输出里没有 URL,只有源内部名称,那么去检查源定义文件里name或者URIs字段就能对上号。我建议不要依赖肉眼扫屏幕,日志文件能帮你反复比对。

3.2 第二步:盘点所有源定义文件

系统读取源定义的位置有两个:传统文件/etc/apt/sources.list,以及目录/etc/apt/sources.list.d/。在 24.04 上,官方源通常被放进/etc/apt/sources.list.d/ubuntu.sources。排查时要一起看:

cat /etc/apt/sources.list ls -l /etc/apt/sources.list.d/ cat /etc/apt/sources.list.d/ubuntu.sources

我习惯用 grep 把关键字段全部列出来,这样一眼就能看到哪些源没有写Signed-By:

grep -rn "URIs\|Signed-By\|deb " /etc/apt/sources.list /etc/apt/sources.list.d/

第三方源常见的文件名像example.list、example.sources,里面可能只有一行deb http://...,没有括号选项。看到这种文件基本就可以锁定问题源了。

3.3 第三步:确认密钥环的“三查”

确认源缺Signed-By之后,还要搞清楚对应密钥到底有没有装。做三个检查:

ls -l /usr/share/keyrings/ ls -l /etc/apt/keyrings/ ls -l /etc/apt/trusted.gpg.d/

/usr/share/keyrings/是系统软件包放置 keyring 的目录,/etc/apt/keyrings/是很多第三方安装脚本约定俗成放 keyring 的目录,/etc/apt/trusted.gpg.d/则是旧版 apt-key 遗留的信任区。如果一个源定义里写了Signed-By: /usr/share/keyrings/example-keyring.gpg,但这个文件不存在,那就是典型的“钥匙丢失”问题。

接着还要检查权限。APT 以_apt用户身份执行网络请求和验证,如果 keyring 文件权限是600且属主是 root,那么_apt用户可能读不到,报错信息里会出现类似“not readable by user '_apt'”的提示。正确的权限通常是644。

stat -c "%a %U %G %n" /usr/share/keyrings/example-keyring.gpg

如果 keyring 存在、权限没问题,还可以看一眼里面的密钥指纹:

gpg --no-default-keyring --keyring /usr/share/keyrings/example-keyring.gpg --list-keys

这一步能确认 keyring 里面到底有几把钥匙,是不是被升级过程清空了。

3.4 第四步:区分官方源、第三方源、PPA的特点

排查时要先把源分成三类,因为修法完全不同。

官方源本身带系统默认 keyring,缺失Signed-By报错多半是源文件被改写坏了。第三方二进制仓库,比如某些软件官方提供的 apt 源,一般需要单独 keyring 和单独的Signed-By字段。PPA 则属于第三方在 Ubuntu 生态上搭建的构建服务,在 24.04 里用新的add-apt-repository命令会自动写好带Signed-By的源定义,但如果是从旧系统升级过来的,可能还残留着旧式不完整源定义。

遇到问题先判断类别,再去翻对应的安装文档。我碰到过不少用户把第三方源的文档看完,然后跑回来抱怨官方源报错,其实是搞混了对象。

4. 修复方案:针对三种来源的Signed-By补法

4.1 官方默认源:重建ubuntu.sources里的标准字段

如果排查后确定问题出在官方源,最稳妥的办法不是手动去改 URL,而是把/etc/apt/sources.list.d/ubuntu.sources恢复成标准内容。核心是补上Signed-By,指向系统自带的官方 keyring:

Types: deb URIs: http://archive.ubuntu.com/ubuntu/ Suites: noble noble-updates noble-backports Components: main universe restricted multiverse Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

注意 24.04 的官方源文件里也可能有noble-security,它通常单独指到安全更新仓库。如果你不确定当前系统应该包含哪些套件,最简单的办法是在改之前先备份原文件:

sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak

备份之后把字段补全,再执行sudo apt update。如果网络源本身没问题,这时告警应该消失。官方源修复不需要重新下载密钥,因为ubuntu-archive-keyring.gpg由基础系统提供,几乎一定存在。

4.2 第三方二进制仓库:单独keyring加Signed-By

第三方仓库修复要分三步走。以packages.example.com/ubuntu为例。

第一步,下载公钥并转换为独立 keyring 文件。这里推荐用gpg --dearmor把 ASCII 格式的公钥转成二进制 keyring,而不是直接用apt-key:

curl -fsSL https://packages.example.com/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/packages-example-keyring.gpg

第二步,修改源定义。如果是旧式单行格式文件/etc/apt/sources.list.d/example.list,改成:

deb [signed-by=/usr/share/keyrings/packages-example-keyring.gpg] https://packages.example.com/ubuntu/ noble main

如果是 DEB822 格式的example.sources,则写成:

Types: deb URIs: https://packages.example.com/ubuntu/ Suites: noble Components: main Signed-By: /usr/share/keyrings/packages-example-keyring.gpg

第三步,修复 keyring 文件权限:

sudo chmod 644 /usr/share/keyrings/packages-example-keyring.gpg

这步很关键,我在前面提过_apt用户读取权限的问题。文件权限不对,即使Signed-By写对了,APT 依然会报错。

4.3 历史遗留PPA:用add-apt-repository安全重置

如果你确认源是一个 PPA,尽量不要手动拼接Signed-By,因为 PPA 的公钥 URL 是特定服务生成的,手动写错一个字符都会导致验证失败。标准做法是先移除再重新添加:

sudo add-apt-repository --remove ppa:example-team/example-ppa sudo add-apt-repository ppa:example-team/example-ppa

在 Ubuntu 24.04 上,add-apt-repository会帮你把 keyring 下载到/etc/apt/keyrings/或者写入合适的位置,并自动在源定义中补上Signed-By。如果命令因为源已经损坏而无法执行,那就要先手动删除对应的源文件:

sudo rm /etc/apt/sources.list.d/example-team-example-ppa-*.list

或者删除.sources文件,然后再用add-apt-repository重新添加。这比手动去找 PPA 的公钥指纹要省事得多。

4.4 特殊自建源:指向本地keyring的完整实例

如果你维护自建软件仓库,处理思路和第三方仓库一致,但可以同时用多个字段控制细节。比如只对某个架构开放:

Types: deb URIs: https://mirror.internal.example/repo/ Suites: noble Components: main Architectures: amd64 arm64 Signed-By: /usr/share/keyrings/self-hosted-keyring.gpg

多写一个Architectures字段的好处是,避免 APT 去抓取本机根本不关心的架构索引,减少apt update的工作量和困惑。如果你还想限制语言文件,可以再加Languages: en之类的字段,但这和Signed-By无关了。

必须强调一句:如果仓库根本没有任何签名,那么任何Signed-By都没法解决。这时你要么给仓库生成并配置签名密钥,要么只能临时用trusted=yes绕过。用trusted=yes等于告诉 APT 这个源不需要验证,只适合在内网测试环境临时使用,公网机器上这么干等于把自己暴露在中间人攻击风险里,我非常不建议。

5. 修复后的验证与默认参数检查

5.1 apt update“零告警”才叫修复完成

补完Signed-By之后,重新执行sudo apt update,并且要确认输出里没有W:相关消息。有时候告警不会立刻消失,这是因为 APT 对源的缓存还停留在旧状态,可以先清理缓存再试:

sudo rm -rf /var/lib/apt/lists/* sudo apt update

清理lists目录会强制 APT 重新下载所有源索引。这一步也能验证新的Signed-By是否真正生效,因为签名验证失败时 APT 会在下载阶段直接报错。

如果 update 正常,再用apt policy查看某个软件包是否能正确看到候选版本:

apt policy example-package

能看到候选版本,说明源索引已经被正常读取。此时还要再确认没有遗留错误:

sudo apt upgrade --dry-run

5.2 验证密钥环权限的几个关键点

修复完成后,我给每个处理的机器做一次权限快照,防止修复无效。关键点是 keyring 必须能同时被 root 和_apt用户读取,目录也要能进入。如果放在/usr/share/keyrings/下,目录本身应该是755;文件最好是644。

用下面这条命令可以批量检查:

find /usr/share/keyrings /etc/apt/keyrings -type f -name "*.gpg" -exec ls -l {} \;

如果哪个 keyring 权限异常,直接改:

sudo chmod 644 /path/to/keyring

另外要注意,用curl下载公钥之后再gpg --dearmor转换出来的 keyring 文件,默认属主是当前用户。如果当前用户是普通用户,用sudo写入/usr/share/keyrings/后属主会变成 root,这是好事。但如果文件被写进某个用户主目录下的keyrings文件夹,APT 可能因为路径不在系统目录里而影响读取,这时候我会把 keyring 统一挪到/usr/share/keyrings/下,因为这是最标准的位置。

5.3 不同报错变体会有什么不同表现

修了这么多次,我发现同一个根因可以表现出不同的报错文案,整理成表格方便对照:

报错表现常见根因处理方向
告警提示 Signed-By is not set (sources.list(5))源定义缺少 Signed-By 字段按源类型补上字段并指向正确 keyring
错误提示 repository does not have a Release file源 URL 或套件名不对,或源被安全机制跳过核对 URIs、Suites 和仓库实际目录结构
密钥文件存在但无法读取keyring 权限或属主不对将权限设为 644,放在 APT 可读目录
提示 key is stored in legacy trusted.gpg.d使用了旧版 apt-key 机制迁移到独立 keyring 并更新 Signed-By
提示 no public key / KEYEXPIREDkeyring 缺失或密钥过期重新下载公钥并更新指纹

看到表格里第一条和第二条经常同时出现,因为 APT 因签名校验失败而跳过源,往往也会连带提示找不到 Release 文件。不要只盯着E:行处理,先解决Signed-By缺失,再回头看E:是否自然消失。

6. 预防下次踩坑:升级前后要做的小动作

6.1 升级前备份源配置和密钥

Ubuntu 大版本升级之前,最值得做的备份操作就是打包/etc/apt目录。源配置、keyring、自定义权限都在这里:

tar czf /tmp/apt-backup-$(date +%Y%m%d).tar.gz /etc/apt

升级后如果源报错,直接解压对比就能看出是哪个文件被动过。我处理过太多类似问题,用户根本想不起来升级前装过什么第三方源,备份就是最后的对照答案。

升级过程也可能触发新 apt 版本对旧格式的容忍度变化,所以升级完的第一件事是sudo apt update,而不是急着去安装软件。看到任何Signed-By告警,先记下来,不要用trusted=yes糊弄过去。

6.2 养成手动维护sources文件而不是依赖脚本的习惯

第三方安装脚本的写法参差不齐,有的会执行apt-key,有的会把源写入/etc/apt/sources.list.d/但完全不理会 keyring。在 24.04 上,我给自己的原则是:任何第三方源,一律手动走“独立 keyring + Signed-By”流程。

下载公钥时,优先选择仓库官方提供的key.gpg文件,而不是从某个 PGP keyserver 随机拉取,因为 keyserver 上的公钥指纹和仓库实际签名用钥可能不一致。如果仓库文档里已经给了明确的 keyring 下载链接,直接用那个链接,签名验证的匹配概率最高。

在手动维护源文件时,我还习惯在每个源文件顶部写注释,注明这个源是给哪个软件用的、密钥文件在哪。下次升级系统出问题时,不用满目录翻找上下文。

6.3 我处理这类问题时的几条原则

这类报错看起来吓人,实际上每次根因都很固定:要么Signed-By没写,要么写了但指向的 keyring 不存在,要么 keyring 存在但权限不对。排查顺序就按这个来:先定位源,再看 keyring,最后改配置。

我自己在 Ubuntu 24.04 上维护第三方源时,会刻意少用ppa:这种带全局信任色彩的方式,尽量每个源一个 keyring。效果是升级之后其他同事的机器陆续出现Signed-By报错,而我这台永远干净。所谓“避坑”,其实就是把当初踩过的每一步都固化成默认习惯。

如果你现在手头正被这个报错卡住,我的建议是:先别急着删源或加trusted=yes,按文章第三部分的排查链路走一遍,定位到具体源之后,再对照第四部分的修复方案操作。整个过程不会超过十分钟,而且修完后你会对 APT 的安全模型有一个非常扎实的理解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 21:26:17

AI时代如何高效读代码:把AI当导游而非替身

1. 这不是教你怎么“抄代码”,而是教你如何让AI成为你读代码时的资深向导“AI 时代怎么读代码:把 AI 当导游,别当替身”——这句话我第一次看到时,手边正开着三个终端窗口:一个在跑某开源项目的单元测试,一…

作者头像 李华
网站建设 2026/10/20 21:25:41

WebSocket消息推送实战:从选型到生产环境的完整指南

我印象很深的一次需求,是某设备告警平台需要把成千上万台设备的告警事件实时推送到运营后台和移动端。团队评估后,最终决定用WebSocket消息推送作为核心通道。当时想得很简单:不就是建连接、收消息嘛。真正落地后才发现,从方案选型…

作者头像 李华
网站建设 2026/10/20 21:23:47

TensorRT INT8量化实战:从校准数据到工程化加速推理

从一次上线前的性能压测说起。某检测项目里的模型在GPU上用FP32的TensorRT引擎跑得“还行”,单路延迟七八毫秒,看着能用。但业务方提了个需求:一块显卡要同时处理4路视频流,延迟还不能涨太多。压测一跑,显存带宽直接被…

作者头像 李华
网站建设 2026/10/20 21:23:39

Windows 11睡眠功能详解:设置、排查与休眠策略指南

你有没有过这种时刻:电脑上开着十几个网页、一份写到一半的文档、几个排队等导出的文件,突然有人喊你,得离开半小时。关机吧,舍不得这个现场;不关吧,屏幕亮着费电,公共场合也怕人乱动。这时候Wi…

作者头像 李华
网站建设 2026/10/20 21:22:23

ctfshow命令执行实战:从PHP绕过到云原生执行面攻防

1. 这不是“打CTF”,而是真实渗透链路中的命令执行切片“ctfshow命令执行”——这个标题在安全圈里几乎成了某种暗号。它不像“SQL注入”或“XSS”那样自带教科书定义,也不像“Log4j”那样因爆发式漏洞登上新闻头条;它更像一个被反复锤炼过的…

作者头像 李华
网站建设 2026/10/20 21:21:14

AI应用架构师实战指南:从传统架构到智能化升级

这两年我明显感觉到,企业内部对“智能化升级”的讨论热度起来了。老板们开口闭口都是要接入大模型,要提效,要降本。但真到了落地环节,问题就来了:模型选哪一个?数据怎么接?业务部门提的需求能不…

作者头像 李华