LabHub
学习 学习路径 课程

RHEL 系管理

要装进介质的六样东西

在 LabHub 中继续学习

一句话总结

导入介质中不能只放 rpm。rpm、repodata、GPG 密钥、清单、校验和、安装操作手册六项缺一不可。实际最常遗漏的是 GPG 密钥与清单

概念图: rpm、repodata、GPG 密钥、清单、校验和、安装操作手册 · GPG 密钥与清单 · 迁移解析后的结果 · 系统中尚不存在的

为什么需要这些内容

在联网环境中成功执行的下载命令,如果安装目标的版本、体系结构或既有安装状态不同, 就无法保证在隔离网络中得到相同结果。遗漏依赖项会导致重复导入;如果缺少用于 验证来源的密钥或批准清单,即使文件已经存在,也无法证明它获得了安装许可。因此, 导入包不能只是一组软件包,而必须成为同时包含复现条件与验证依据的部署单元。

它是如何工作的

在外部下载

有两种路径。

迁移解析后的结果

dnf download --resolve --alldeps --destdir=/srv/bundle/rpms httpd mod_ssl

只使用 --resolve 时,仅会下载当前设备上没有的内容。如果目的是制作隔离网络导入包,这个结果几乎总是错误的。

然而,只有 --alldeps 仍然不够,因为依赖解析本身依然以当前系统的状态为前提。如果联网设备是 9.4,而目标是 9.2,结果就可能不同。规范做法是使用空根目录。

mkdir -p /var/tmp/airgap-root
dnf download --installroot=/var/tmp/airgap-root --releasever=9.4 \
  --setopt=reposdir=/etc/yum.repos.d --resolve --alldeps \
  --destdir=/srv/bundle/rpms httpd mod_ssl

必须同时指定 --releasever 文档中的警告是:“创建 installroot 时如果不使用 --releasever$releasever 的值会从 installroot 内的 rpmdb 读取;而 rpmdb 在创建时为空,因此事务会失败。”

迁移整个仓库

dnf reposync --repoid=rhel-9-for-x86_64-baseos-rpms \
  --download-path=/srv/sync --download-metadata --gpgcheck \
  --newest-only --arch=x86_64 --arch=noarch --remote-time

主要选项:--download-metadata(同时下载元数据)、--gpgcheck(删除签名验证失败的软件包,只要删除一个就以退出码 1 结束)、--newest-only(每个仓库只保留最新版)、--delete(删除远端已不存在的内容)、--norepopath(路径中不附加仓库名称)。

陷阱:同时使用 --newest-only--download-metadata 时,虽然只下载最新软件包,元数据中却仍然保留旧软件包的信息。 在内网请求某个旧版本时,就会出现元数据称其存在、实际文件却缺失的状态。

清单

清单必须包含五项内容:完整的 NEVRA(Name、Epoch、Version、Release、Architecture)、每个软件包的 SHA-256、快照日期、使用的 releasever、来源仓库 ID。

rpm -qp --queryformat '%{NAME}\t%|EPOCH?{%{EPOCH}}:{0}|\t%{VERSION}\t%{RELEASE}\t%{ARCH}' "$f"
sha256sum "$f" | cut -d' ' -f1

epoch 的三元表达式是关键。mod_ssl 这样的软件包,其 epoch 为 1,但文件名中完全没有这个数字。

在内部验证

rpmkeys --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
rpmkeys --list
rpmkeys --checksig /srv/bundle/rpms/*.rpm | grep -v 'digests signatures OK'

最后一行没有任何输出,就表示全部正常。此外,还要检查介质中存在、清单里却没有的文件

comm -13 <(cut -f7 MANIFEST.tsv | sort) <(cd rpms && ls -1 *.rpm | sort)

缺失文件会很快以安装失败的形式暴露出来,而额外文件却可能无人察觉地通过。从导入审批的角度看,后者是更严重的问题。

在内部建立仓库

createrepo_c /srv/repo/labhub
cat > /etc/yum.repos.d/airgap.repo <<'EOF'
[airgap-baseos]
name=RHEL 9 BaseOS (airgap local, snapshot 2026-08-20)
baseurl=file:///srv/repo/labhub
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
metadata_expire=-1
EOF
dnf --disablerepo='*' --enablerepo=airgap-baseos install -y httpd

实际工作中会遇到的情况

遗漏体系结构。 在 x86_64 笔记本上下载后导入 ARM 服务器,会在不报错的情况下带入错误的软件包。如果在 --arch 中没有同时指定 noarch,Python 模块或配置软件包也会全部遗漏。

下一个实验要做什么

制作导入包,使用清单进行验证,将其打包为归档文件后再解压,建立仓库,并且只依靠这个仓库完成安装。