Rocky 和 AlmaLinux 如何启用 EPEL 与 CRB
Rocky Linux 和 AlmaLinux 中 dnf 找不到软件包并不代表系统损坏。了解 BaseOS、AppStream、CRB 的区别,安全启用 EPEL,并避免第三方仓库接管基础系统。
为什么 dnf 找不到您需要的软件包
EPEL 和 CRB 是全新的 Rocky Linux 或 AlmaLinux 服务器默认不会提供的两个软件仓库,因此在新服务器上,dnf install htop 会返回 No match for argument: htop,随后返回 Error: Unable to find a match: htop。系统没有损坏,也不是镜像站点不可用。基础发行版有意只提供少量软件包;CRB 已存在,但处于禁用状态;EPEL 则是单独的社区软件仓库,需要手动添加。
在 Ubuntu 上,同一个软件包位于 universe 中,而 universe 在几乎所有云镜像中都已启用,因此通常不会出现这个问题。Red Hat 系列以不同方式划分软件包,默认提供的软件包更少。解决方法只需执行 3 条命令。本指南接下来说明一些通常不会在第一周告诉您的内容:这些软件仓库能提供什么、不能提供什么,以及如何防止第三方软件仓库在后台接管基础系统。
这些命令的验证方式。我们的命令测试容器仅运行 Ubuntu,因此下面的 dnf 命令没有在我们自己的测试机器上执行。命令依据 Rocky Linux 和 AlmaLinux 文档编写。每一步都说明了应看到的输出,因此请在您自己的服务器上逐项检查,不要一次性粘贴并执行整个代码块。
BaseOS、AppStream 和 CRB 是什么?
BaseOS 是操作系统本身,包括内核、glibc、systemd 和核心用户空间。这里的软件版本在整个大版本生命周期内保持不变,安全修复会回移植到这些固定版本中。BaseOS 中看起来像多年前的版本号,并不表示软件包没有打补丁,而是表示它仍是旧版本,但已经应用了补丁。这正是企业级发行版的核心设计。
AppStream 包含运行在操作系统之上的软件,例如 Web 服务器、数据库、语言运行时、编辑器和监控代理。在版本 8 中,AppStream 的许多内容通过带有备用流的模块提供,因此 dnf module list 很重要。你需要选择一个流,例如某个 PHP 流。版本 9 几乎完全取消了模块化,因此在 Rocky 9 和 Alma 9 上,通常直接提供某个软件的一个版本,不需要先启用模块。
Extras 默认启用,内容很少。它主要存放其他软件仓库的发布软件包,epel-release 本身也来自这里。因此,在 Rocky 或 Alma 上安装 EPEL 时,完全不需要信任随机 URL。
CRB 是 CodeReady Builder 仓库,在版本 8 中称为 PowerTools。它包含发行版的构建部分:开发头文件、静态库,以及软件包在构建时需要的测试和文档工具。该仓库已经位于镜像中,但默认禁用。在 Red Hat 自有产品中,同样的内容称为 CodeReady Linux Builder,包含在订阅中;Red Hat 声明该仓库不在支持范围内。Rocky 和 Alma 继承了这些内容以及默认禁用的设置。
对于从 Debian 或 Ubuntu 转来的读者:main 将运行时软件包和 -dev 头文件放在同一个归档中,因此那里没有需要启用的 CRB。与 EPEL 最接近的是 universe,它由社区维护,不提供厂商支持承诺。
EPEL 是什么,以及由谁维护
EPEL 代表 Extra Packages for Enterprise Linux。它是 Fedora 项目的一部分:这些软件包先存在于 Fedora 中,再针对当前企业版发行版重新构建,由 EPEL Special Interest Group 维护。该小组成员主要是 Fedora 社区志愿者。Red Hat 提供构建和镜像基础设施,也有一些 Red Hat 工程师负责维护其中的软件包。双方的关系仅限于此。EPEL 不是 Red Hat 产品。 EPEL 软件包不附带支持合同,也不提供 SLA(服务级别协议),无论是在 RHEL 上还是在其重构版本上。
EPEL 能够安全启用,依靠的是一项策略:EPEL 软件包绝不能替换基础发行版中的软件包。如果 AppStream 提供 nginx,EPEL 就不会提供该软件包。负责审核 EPEL 软件包的人员会执行这项规则,因此这项承诺仅适用于 EPEL。它无法保护您免受之后添加的其他软件源影响。
EPEL 的生命周期承诺也不同于基础发行版,这一点通常会在第 3 年造成问题。BaseOS 软件包版本会在主版本的整个 10 年生命周期内保持不变。EPEL 维护者承诺的时间窗口短得多:至少覆盖 1 个 RHEL 次要版本或 13 个月,以较短者为准。实际上,大多数软件包的维护时间会远超这一期限。有些软件包会在维护者停止维护后退役;有些软件包会在发行版生命周期中途升级到新的主版本,因为 EPEL 会跟随 Fedora。因此,一次例行的 dnf upgrade 可能会在您认为稳定的服务器上安装 EPEL 工具的新主版本,而您依赖的软件包也可能在没有任何您能收到的通知的情况下停止获得更新。
启用 EPEL 前还应了解另一个后果:EPEL 基于最新的 RHEL 次要版本构建。如果您通过冻结的镜像或供应商的特定版本软件源,将服务器固定在较旧的次要版本上,EPEL 软件包可能需要比现有版本更新的基础库。dnf 会将此报告为缺少依赖项,看起来像是镜像问题,实际原因却是版本不一致。
在 Rocky 或 Alma 上启用 CRB 并安装 EPEL
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --set-enabled crb
sudo dnf install -y epel-release
sudo dnf makecache
dnf repolist --enableddnf repolist --enabled 现在应列出 baseos、appstream、extras、crb 和 epel。您还可能看到一个小型的 epel-cisco-openh264 条目,这是由 epel-release 添加的。如果列表中缺少 crb,说明启用步骤未生效,下一节将解释原因。
在 Rocky 8 和 Alma 8 上,该存储库仍称为 PowerTools,因此中间的命令应改为 sudo dnf config-manager --set-enabled powertools。存储库 ID 区分大小写。较旧的 CentOS 8 文档将其写为带大写字母的 PowerTools,这不会匹配。在 AlmaLinux 10 上,从 10.0 起默认启用 CRB 存储库(于 2025 年 9 月变更),因此只需执行 epel-release 步骤。
epel-release 来自 extras,后者已启用,因此无需信任某个 URL,也无需手动导入密钥。该软件包会写入 /etc/yum.repos.d/epel.repo,并将 EPEL 签名密钥安装到 /etc/pki/rpm-gpg/。确认该文件中包含 gpgcheck=1,并忽略任何建议使用 --nogpgcheck 绕过签名错误的指南。签名验证失败表示软件包并非其声称的内容,或者系统时钟不正确。
在 Rocky 上,epel-release 还会在 /usr/bin/crb 安装一个小型辅助工具,因此 sudo crb enable 和 crb status 无需插件即可执行相同的操作。在依赖该工具前,使用 command -v crb 检查系统中是否存在它,因为并非每个重建版本的每个分支都包含该工具。
要确认 EPEL 确实可访问,而不仅仅是已列出,请请求一个只有该存储库提供的软件包:
dnf repoquery --repo=epel htop该命令会输出软件包名称、版本和架构。没有输出表示存储库已启用,但未返回内容。这通常是镜像或元数据问题,而不是配置问题,因此接下来尝试 sudo dnf clean all && sudo dnf makecache。
dnf 提示找不到 config-manager 命令的原因
这是最常见的第一个问题,而且恰好会出现在大多数 VPS 提供商提供的镜像中。
No such command: config-manager. Please use /usr/bin/dnf --help
It could be a DNF plugin command, try: "dnf install 'dnf-command(config-manager)'"config-manager 是插件,不是内置的 dnf 子命令。它包含在 dnf-plugins-core 中。完整服务器安装会安装该软件包,但最小化镜像、云镜像和容器镜像通常不会安装。dnf 自己给出的建议可以正常工作,因为该软件包声明了这个虚拟能力:
sudo dnf install -y 'dnf-command(config-manager)'请直接使用该命令。括号是 shell 语法,因此不加引号的版本会产生语法错误,而不是 dnf 错误。
如果需要使用的仓库处于禁用状态,导致无法安装该插件,请直接编辑配置文件。找到包含该仓库段的文件,打开它,然后在 [crb] 下设置 enabled=1:
grep -rl crb /etc/yum.repos.d/这正是 config-manager 写入的内容,因此手动修改不会丢失任何配置。dnf repolist --enabled 可确认结果。
部分 EPEL 软件包必须先启用 CRB 才能安装
第二个常见问题给出的错误信息不会提到 CRB。某个 EPEL 软件包依赖的库只在 CRB 中提供时,依赖解析会失败。错误信息会列出该库以及需要它的软件包:
Error:
Problem: conflicting requests
- nothing provides libexample.so.0()(64bit) needed by examplepkg-1.4-2.el9.x86_64 from epel原因是 CRB 未启用,因此 dnf 找不到唯一提供该库的软件仓库。按顺序检查以下两项:
dnf repolist --enabled
dnf --enablerepo=crb repoquery --whatprovides 'libexample.so.0()(64bit)'如果第二条命令列出某个软件包,但直接安装仍然失败,说明 CRB 未启用。这类错误很常见,因此 AlmaLinux 在版本 10 中专门默认启用 CRB,以避免此问题。--enablerepo=crb 也可以作为单次安装的选项使用,但如果使用 EPEL,应永久启用 CRB,因为下一次 EPEL 更新可能会引入新的 CRB 依赖,而不会提前提示。
这个软件包来自哪个仓库?
启用 4 个仓库几周后,真正有用的问题不再是安装了什么,而是这些软件包来自哪里。
dnf repolist --all
dnf info htop
dnf repoquery --installed --qf '%{from_repo} %{name}' | sort | uniq -c | sort -rn
dnf repository-packages epel list installed对已安装的软件包运行 dnf info 会输出一行 From repo。dnf list installed 会在第三列显示相同信息,并在前面加上 @。因此,@epel 表示该软件包来自 EPEL,@System 表示 dnf 不知道其来源。这通常意味着有人对下载的文件运行了 rpm -i。repoquery 会按仓库统计数量。借助它,可以快速发现一台接手的服务器上有 40 个软件包来自一个你从未听说过的仓库。最后一个命令会准确列出某个仓库提供给你的所有软件包。删除该仓库前,你需要先获取这份清单。
这里对应的 apt 用法是 apt-cache policy <package>。第一个月建议在第二个标签页中打开dnf 和 apt 命令对照,因为即使标志不同,两者的概念也能直接对应。
如何阻止第三方仓库替换基础软件包?
EPEL 承诺不会这样做。其他仓库都没有此承诺。数据库、代理或语言运行时的厂商仓库可能提供自己的库版本,而 BaseOS 也提供同名库。dnf 会安装该版本,因为 dnf 的默认规则很简单:无论软件包来自哪里,都选择版本号最高的版本。
两个控制项可以解决大多数问题,而且都位于 /etc/yum.repos.d/ 下的仓库文件中。
priority= 决定多个仓库提供同名软件包时由哪个仓库优先。数值越低,优先级越高;默认值为 99。因此,应为基础仓库设置较低的数值,为第三方仓库设置较高的数值。这样,即使第三方版本更新,dnf 也会选择基础软件包。现代版 dnf 会自行处理这一点,因此 CentOS 7 时代的独立 yum-plugin-priorities 软件包已经不再是解决方案的一部分。
includepkgs= 是更强的过滤选项。excludepkgs= 会阻止仓库提供指定名称的软件包,但这要求您预先判断该仓库可能提供哪些软件包。includepkgs= 则相反:该仓库只能提供这些名称的软件包,不能提供其他软件包。如果某个厂商仓库只应提供其自身的代理软件包,只需配置一行。
[vendor-tools]
name=Vendor tools for EL9
baseurl=https://packages.example.com/el9/x86_64/
enabled=1
gpgcheck=1
gpgkey=https://packages.example.com/RPM-GPG-KEY-vendor
priority=90
includepkgs=vendor-agent,vendor-agent-plugins在版本 8 中,还需要了解一个设置。第三方仓库中的软件包可能会因为 AppStream 模块提供了同名软件包而被隐藏。该仓库的配置段中的 module_hotfixes=1 会告知 dnf 停止执行此过滤。如果软件包对 dnf repoquery 可见,但无法在版本 8 的系统上安装,通常就是这个原因。版本 9 几乎移除了所有模块,因此很少会遇到此问题。
要将一个软件包固定到指定版本,请安装 python3-dnf-plugin-versionlock,然后使用 sudo dnf versionlock add <package>。这相当于 apt-mark hold。请注意一个容易让 Debian 用户混淆的差异:在 apt 中,较高的 Pin-Priority 优先;在 dnf 中,较低的 priority 优先。
混用 RHEL 相邻发行版的软件仓库会使服务器无法升级
Rocky、Alma、CentOS Stream、Oracle Linux 和 RHEL 足够接近,因此它们的软件包可以相互安装;但它们之间又存在足够差异,最终会得到一个无人能够支持的系统。
其根本原因是版本号。CentOS Stream 9 的版本进度领先于 RHEL 9。因此,即使只将 Rocky 9 服务器指向 Stream 仓库一次,甚至只安装一个软件包,也会留下版本高于 Rocky 后续发行版本的软件包。下一个 Rocky 次要版本发布后,其中该软件包的版本会低于当前已安装版本,因此 dnf upgrade 不会处理它。此时,服务器运行的是一种无人测试过的软件包组合,并且可能在你以为系统已完成补丁更新的情况下,悄然维持数年。
常见表现是 dnf upgrade 报告没有需要执行的操作,而 sudo dnf distro-sync 建议降级一长串软件包。distro-sync 是修复工具:它会强制所有已安装软件包与启用的软件仓库实际提供的版本保持一致,其中也包括降级。先禁用外部仓库,再运行该工具;接受前先查看它列出的变更。旧版 RPM 已不在镜像中时,修复会失败。此时,从干净镜像重建服务器,比继续处理依赖解析器更快、更安全。
ELevate 遗留项是这一问题的另一种常见形式。ELevate 是基于 Leapp 构建的 AlmaLinux 迁移工具,可用于将 CentOS 7 服务器升级,或在不同重建发行版之间转换。迁移过程仓促时,/etc/yum.repos.d/ 中可能仍然存在 EL7 仓库文件,系统中也可能仍安装 EL7 软件包。使用 rpm -qa | grep el7 查找这些项目。每个项目对应一个任何已启用仓库都无法更新的软件包。之后再次运行 Leapp 时,它会将这些软件包报告为无法映射的软件包,从而阻止升级;你必须手动清理这些项目。应在服务器运行稳定时清理它们,不要等到需要进行下一次大版本升级时再处理。
供应商仓库中的软件包覆盖 AppStream 软件包,是同一问题较轻的一种表现,上面的 includepkgs 行就是解决方法。容器工具最常出现这种情况,因为 Docker 自有仓库中的 containerd.io 与 AppStream 中的 runc 会发生冲突,因此必须保留其中一个并移除另一个。确定选择后记录排除规则,并按已验证的顺序执行:在 Rocky Linux 上安装 Docker教程说明了应先移除哪些发行版软件包。
仓库的 apt 到 dnf 对照
/etc/apt/sources.list.d/*.sources对应/etc/yum.repos.d/*.repo,其中一个文件可以包含多个[sections],每个都有自己的 id。add-apt-repository universe对应dnf install epel-release,但universe仍属于 Ubuntu 自有的软件仓库,而 EPEL 是独立项目。apt update没有对应项,这一点需要记住。dnf 会按自身计划刷新元数据,dnf makecache可立即强制刷新。apt-cache policy <pkg>对应dnf info <pkg>,加上dnf list --showduplicates <pkg>可查看所有可用版本。apt-mark hold对应dnf versionlock add,来源为python3-dnf-plugin-versionlock。- 在
/etc/apt/preferences.d/中使用 pinning,对应于仓库部分中的priority=,但数值方向相反。 dpkg -S /path/to/file对应rpm -qf /path/to/file。
自动更新需要转换的是实现思路,而不是语法,因为这里没有 unattended-upgrades。计时器、配置文件以及是否重启的问题,见Rocky 和 Alma 上的 dnf-automatic。
缩短软件仓库列表
启用 CRB,安装 epel-release,然后记录执行的操作及其原因。可以将记录写入配置管理系统,也可以写入服务器上的普通文件。服务器运行三年后由其他人接手时,这份记录的价值往往超出预期。
添加软件仓库前先进行搜索。运行 dnf search,然后运行 dnf info,最后再考虑添加新仓库。人们启用 EPEL 的许多软件已经包含在 AppStream 中。系统监控就是最明显的例子,因为 Performance Co-Pilot 已包含在基础软件仓库中,不需要任何第三方软件仓库。每增加一个软件仓库,就多一个可以在某个星期二向服务器发布软件包的外部方;每个软件仓库都会增加下一次大版本升级的难度。
如果你仍在两种发行版之间进行选择,那么两者的软件仓库布局完全相同,epel-release 的行为也一致。真正的差异在其他方面:Rocky Linux 与 AlmaLinux 的比较介绍了两者的重建理念,因为 AlmaLinux 现在以 ABI(应用程序二进制接口)兼容性为目标,而不是逐行重建。
FAQ
如何在 Rocky Linux 9 或 AlmaLinux 9 上启用 EPEL?
先运行 sudo dnf install -y dnf-plugins-core,然后运行 sudo dnf config-manager --set-enabled crb,最后运行 sudo dnf install -y epel-release。使用 dnf repolist --enabled 确认,输出中应列出 baseos、appstream、extras、crb 和 epel。安装 EPEL 软件包前先启用 CRB,因为其中许多软件包依赖只有 CRB 提供的库。在版本 8 中,仓库 ID 是 powertools,而不是 crb。
在生产服务器上启用 EPEL 是否安全?
EPEL 得到了广泛使用,并且遵循一项策略:EPEL 软件包不会替换基础发行版中的软件包。因此,启用 EPEL 不会改变 BaseOS 或 AppStream 提供的内容。但需要注意支持问题:EPEL 是 Fedora 社区维护的项目,不提供服务级别协议;维护者对某个软件包的承诺期限可能只有一个 RHEL 次要版本周期或 13 个月。使用 dnf repository-packages epel list installed 维护软件包清单,并对任何供面向客户的服务依赖的 EPEL 软件包使用 dnf versionlock。
为什么 dnf 提示 no such command: config-manager?
因为 config-manager 是 dnf 插件,而不是内置命令;精简镜像或容器镜像通常不会预装 dnf-plugins-core。提示本身已经给出了解决方法:sudo dnf install -y 'dnf-command(config-manager)'。其中使用引号,以免 shell 将括号解析为特殊字符。如果暂时无法安装任何软件包,请运行 grep -rl crb /etc/yum.repos.d/,打开该命令指出的文件,然后在 [crb] 部分手动设置 enabled=1。
CRB 和 PowerTools 有什么区别?
它们是同一个仓库的两个名称。版本 8 称其为 PowerTools,ID 为 powertools;版本 9 及更高版本称其为 CRB,ID 为 crb;Red Hat 自己的产品则将该内容称为 CodeReady Linux Builder。该仓库提供开发头文件、静态库和构建时工具,在 Rocky 和 AlmaLinux 9 上默认禁用。AlmaLinux 10 从 10.0 开始默认启用该仓库,因此在 AlmaLinux 10 上运行启用命令前,请先检查 dnf repolist --enabled。
如何再次移除 EPEL,同时避免破坏系统?
先使用 dnf repository-packages epel list installed 生成清单,因为仅移除 epel-release 软件包不会移除从 EPEL 安装的任何软件包。这些软件包会继续保留在磁盘上,但失去更新来源,也不再获得安全修复,系统不会提供任何错误提示。逐个评估软件包,移除或替换不再需要的软件包,然后再运行 sudo dnf remove epel-release。如果某个来自 EPEL 的软件包没有替换任何其他软件包,并且确实必须移除,sudo dnf repository-packages epel remove 可以在一个事务中清除这组软件包,因此确认前请仔细查看拟执行的列表。