公司动态

openEuler离线升级包制作:从dnf抓包到内网本地repo部署全流程

📅 2026/9/2 19:43:58
openEuler离线升级包制作:从dnf抓包到内网本地repo部署全流程
简介这份离线升级包面向 openEuler 系统管理员与运维人员用于将 openEuler 22.03 LTS SP1 平滑升级至 SP3尤其适合内网隔离、无法访问外部软件源的服务器环境。包内已按升级需求处理了 rpm 依赖关系并在全新安装的 SP1 系统上验证通过可显著减少离线升级时逐个排查依赖、反复下载补丁的工作量。资源共 508 个文件主要包含 501 个 rpm 升级包另有 3 个 gz、3 个 bz2 和 1 个 xml 文件用于构建本地 yum 源时提供仓库元数据整体压缩包约 389.15 MB。文件结构接近标准软件源布局既可直接按清单应用升级也可挂载为本地源供批量主机使用。目前已有 906 人学习下载适合需要在无外网条件下完成 openEuler SP1 到 SP3 升级的运维场景。 所谓“补丁”平时有网的时候就是个dnf upgrade -y的事可一旦服务器部署在隔离内网、只开放业务端口公网 yum 源根本连不上这时候你就知道离线升级包有多救命。我最近刚给一批搭载 openEuler 22.03 LTS SP3 的服务器做过一轮补丁同步踩了不少坑也理顺了一套从“联网机器抓包”到“内网机器装包”的标准流程。这篇就把完整做法、命令和坑都写出来给正被离线升级折磨的运维同学一个可抄的作业。先说清楚适用范围openEuler 22.03 LTS 是长期支持版本SP3 是它的第三个服务包和 SP2 相比主要是把前面若干个月的 bug 修复、CVE 安全补丁统一打包推进。如果你在内网维护的是 x86_64 或 aarch64 两种架构的机器且没有公网权限那这篇文章就是给你准备的。1. 先理解离线升级包的层次补丁包、软件仓库、全量 ISO很多人一听到“离线升级包”脑子里以为就是下载几个 RPM 文件拷进去装。真到生产环境你会发现这种思路在只有三五个依赖的小软件上或许可行但一旦涉及 glibc、openssl、kernel 这种底层组件依赖链条会瞬间膨胀到几十上百个包。手工一个个rpm -ivh大概率会把系统搞坏所以我更倾向于把它拆成三个层次来理解。第一层是“单机补丁包”适合离线装某个具体软件比如 Docker、Nginx顶多带上一二十个依赖。做法是用联网机器把指定包及其依赖下载成 RPM 文件拷贝进内网后逐个安装。第二层是“本地软件仓库”把一批 RPM 按目录组织好用 createrepo 生成 repodata 元数据在内网机器上配置一个本地 repo 源之后还能继续用 dnf 来做依赖解析和升级这是我最推荐的方式也是这篇文章的主线。第三层是“完整 ISO 全量源”从 openEuler 官方镜像站下载 Everything 版 ISO挂载后直接作为离线源使用适合一次性部署新系统而不是日常补丁升级。日常补丁场景里我实际用得最多的是第二层。因为 SP3 的补丁不是静态的官方仓库会持续更新一次拷 ISO 进去三个月后又落后了。做成本地 repo内网机器每次升级只需要从这台“中转机”同步增量 RPM路径短、可控性强、风险也低。做之前还有一件事要搞清楚你的目标机器架构。openEuler 的软件源按 x86_64、aarch64 严格分离别在 x86 机器上抓 aarch64 的包反过来也不行。离线升级包的第一原则就是架构一致、同版本基线一致否则后面全是坑。2. 制作离线升级包联网机器上的完整操作链路制作离线升级包需要一台“中转机”它必须满足两个条件能和 openEuler 的 yum 源正常通信且和目标内网机器是同一个大版本、同一个架构。这台机器不需要完全一样但尽量干净避免把实验环境里乱七八糟的第三方源带进抓包结果。2.1 配置干净的 yum 源别把第三方源混进来中转机系统装好 openEuler 22.03 LTS SP3 后第一步是检查/etc/yum.repos.d/下的仓库文件。官方源至少要保留OS、everything、EPOL、update、source这几个常用 repo 名称每个 repo 内部有baseurl指向 mirror 站点。第三方用 noarch 的软件源建议在抓包期间先禁用避免 dnf 自动把非官方依赖包拉进来导致内网安装时签名或版本混乱。我在实践中还会固定一下源地址直接用官方 mirror 列表里某个节点。因为 dnf 默认会做 mirrorlist 轮询抓包过程中如果经常在不同节点之间跳偶尔会出现个别文件命中 404。写死一个 node 能减少这种偶发问题。# 查看当前启用的仓库 dnf repolist # 确认系统版本 cat /etc/openEuler-release # 查看架构 uname -m执行完这三条确认系统是 openEuler 22.03 LTS SP3架构是 x86_64或你目标的 aarch64再往下走。2.2 先看有哪些补丁可升级dnf check-update在抓包之前我习惯先执行dnf check-update看看这个 22.03 LTS SP3 基线到底落后了多少个补丁。输出结果里会列出可更新的包名、仓库来源和版本号。这一步有两个作用一是确认中转机的源确实能拉到更新二是对升级包规模有个心理预期。dnf check-update如果输出一大堆说明 SP3 基线之后的更新积累了不少如果输出为空说明 SP3 的 update 仓库已经和当前版本一致不需要做离线升级包。这里要注意check-update的输出结果是动态的今天看到的包和明天看到的可能不同所以离线升级包本质上是一个“快照”打在包上的版本号才是最终生效的版本。如果只想为特定软件做离线包比如把 openssl 单独升级可以用dnf list --showduplicates openssl它能列出 openssl 在当前仓库里的所有可用版本然后你用下面第四节里的dnf download方式单独抓这一个包和它的依赖。2.3 全量升级包生成dnf update --downloadonly 还是 reposync对于大多数场景我推荐的是“全量抓取所有可更新包”。这里的全量不是指把整个 openEuler 仓库几十 GB 都拉下来而是把当前基线到最新版本之间、所有存在更新的 RPM 和它们的依赖拉下来。dnf 自带一个 downloadonly 插件直接执行dnf install dnf-plugins-core -y dnf update --downloadonly --downloaddir/data/offline-updates执行完之后/data/offline-updates里就是本次系统全部可更新包的 RPM 文件。这个方法的好处是精准只包含中转机当前环境需要更新的内容。缺点是如果内网机器的软件包组合和中转机不完全一致比如内网多装了一个中转机上没有的软件包那这个目录里可能缺东西。所以我更推荐第二个方案dnf reposync直接同步整个 update 仓库。它不会管中转机装了什么而是把 openEuler update 仓库里所有 RPM 全部拉到本地。缺点是体积大优点是不会漏包内网无论哪台机器都能用它补齐。# 同步 update 仓库包含所有更新包 dnf reposync --repoidupdate --download-path/data/offline-updates --download-metadata如果你连 EPOL、everything 里的软件也要离线分发可以继续dnf reposync --repoidEPOL --download-path/data/offline-updates --download-metadata dnf reposync --repoideverything --download-path/data/offline-updates --download-metadata--download-metadata会把仓库的元数据也拉下来后面让内网本地 repo 直接用省一次 createrepo 的时间。但我在实际使用中还是会重新跑一次 createrepo因为 reposync 拉下来的元数据可能引用的是远程绝对路径本地 repo 场景下反而容易出现路径错乱。2.4 生成或补全本地仓库元数据createrepo_c如果用了 reposync 且下载了 metadata可以直接跳过这步如果是用dnf update --downloadonly抓的包或者想重建一份干净的元数据就需要用 createrepo_c 或 createrepo。dnf install createrepo_c -y cd /data/offline-updates createrepo_c .执行完后目录里会出现repodata文件夹里面是 primary、filelists、other 等元数据文件。这相当于给这堆 RPM 做了一本“目录索引”内网 dnf 拿到这本索引才能做依赖解析、版本对比和事务计算。还有一个细节一定要把 GPG 密钥导出来一起带走。openEuler 的 RPM 包都带官方签名内网机器如果开启 gpgcheck就必须先导入密钥否则 dnf 会报签名验证失败。密钥文件一般在系统里叫RPM-GPG-KEY-openEuler可以通过下面的命令找到并复制到目标目录find /etc/pki/rpm-gpg -name *openEuler* -o -name *openEuler* cp /etc/pki/rpm-gpg/RPM-GPG-KEY-openEuler /data/offline-updates/到这一步离线升级包内容上已经完整了RPM 文件 repodata 元数据 GPG 密钥。接下来就是打包传输。3. 从联网机器到内网机器repo 配置与升级执行离线升级包制作完成只是第一步真正容易翻车的是把它安全地送进内网并让目标机器认账。整个过程我习惯拆成三步打包校验、配置本地 repo、执行升级。3.1 打包传输与三次校验/data/offline-updates目录可能很大一般用 tar 压缩传输。内网没有飞书网盘、没有共享文件夹最朴素的办法就是 U 盘拷贝或者用运维跳板机作为文件转发节点。打包命令cd /data tar czvf offline-updates.tar.gz offline-updates sha256sum offline-updates.tar.gz offline-updates.sha256传输到目标机器后先做校验再解压避免传输过程中文件损坏。我遇到过 U 盘文件系统问题导致 RPM 解压失败的情况所以强烈建议把 sha256 校验做成固定动作。sha256sum -c offline-updates.sha256 tar xzvf offline-updates.tar.gz -C /opt/解压完成之后目标是/opt/offline-updates里面应该有 repodata 目录、一堆 RPM 文件和 GPG 密钥。3.2 编写内网本地 repo 文件repo 文件是 dnf 识别软件源的“钥匙”路径通常放在/etc/yum.repos.d/下。为了防止内网机器误连外网源我会把所有默认 repo 文件改成.bak后缀或移走只保留离线 repo。这步操作在生产环境要谨慎最好先备份。mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/然后新建一个offline.repo内容如下[offline-update] nameopenEuler 22.03 LTS SP3 offline update repository baseurlfile:///opt/offline-updates enabled1 gpgcheck1 repo_gpgcheck0 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-openEuler这里我把gpgcheck1开着因为 RPM 包本身是官方签名的校验签名能防止包被篡改或损坏。repo_gpgcheck0是关掉对仓库自身元数据的签名校验因为离线仓库的元数据是我们自己生成的没有官方密钥签名硬开会报错。这个组合是内网离线仓库比较实用的配置。写完 repo 文件后导入密钥并重建缓存rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-openEuler dnf clean all dnf makecache如果dnf makecache能正常完成说明本地仓库的元数据和文件路径都没问题。3.3 执行升级与验证最稳妥的做法是先查后更。先看一眼离线仓库到底提供了多少可更新包dnf --disablerepo* --enablerepooffline-update check-update--disablerepo*是强制所有源禁用只开启 offline-update确保内网机器不会偷偷去连其他源。这一步输出如果和你在中转机上看到的版本基本一致说明离线包齐全。然后执行升级dnf --disablerepo* --enablerepooffline-update upgrade -y执行过程中 dnf 会先做事务检查列出将要安装、升级、删除的包确认依赖能闭环。如果提示缺少依赖优先考虑是不是离线包里漏了 noarch 或特定架构的包可以在中转机上用dnf repoquery --requires之类的命令反查。升级完成后重启系统并验证内核版本reboot uname -r如果你的离线包中包含 kernel 更新重启后uname -r应该显示新的内核版本。我还会顺手检查几个关键组件版本比如 openssl、glibc、systemd确认它们和离线包里的版本号一致。4. 离线升级包常见故障现场排查记录离线包看着简单实际操作中各种问题层出不穷。下面这六个问题是我在不同项目里真实遇到过的按发生率从高到低排。4.1 架构不匹配导致的“软件包不存在”在 x86_64 的中转机上抓包拷到 aarch64 的内网机器上dnf 会直接报错说某个包在仓库里找不到或者包名有冲突。因为 RPM 的包名里带了架构标签比如openssl-3.0.7-24.oe2203sp3.x86_64.rpm和...aarch64.rpm完全是不兼容的东西。解法只有一个制作离线包时就严格按目标架构走。如果内网是混合架构建议分别做 x86_64 和 aarch64 两套离线包路径上也要区分开别混在一个目录里。4.2 gpg 签名验证失败公钥没导入或密钥不匹配这是最容易遇到的报错现象是 dnf 输出Public key for xxx.rpm is not installed或GPG key retrieval failed。原因基本都是目标机器没有导入 openEuler 官方 GPG 密钥。解决办法就是前面说的先把密钥拷贝进内网、rpm --import导入再写 repo 文件里指定gpgkey。还有一种情况是你的离线包不是从官方源抓的而是从某个第三方镜像站抓的那 RPM 包的签名可能就和官方密钥对不上。这时不要图省事直接gpgcheck0更稳妥的做法是找到镜像站自己提供的签名公钥或者直接换回官方源重新抓包。生产环境的包来源必须干净这是底线。4.3 dnf 缓存导致升级结果不准确内网机器之前可能遗留了旧的 dnf 缓存这些缓存里记录的是旧仓库的元数据导致dnf check-update显示的结果和离线仓库实际内容不一致。我遇到过最离谱的一次是内网机器显示“没有可用更新”但离线仓库里明明有一百多个 RPM。问题就出在dnf makecache没跑成功或者缓存没刷新。解决方法是执行一次完整的缓存清理dnf clean all rm -rf /var/cache/dnf/* dnf makecache然后把/etc/yum.repos.d/下所有无关 repo 全部禁用确保 makecache 只读离线仓库。如果机器上同时存在多个离线目录的 repo也会引起混乱一个目标机只保留一个离线仓库配置是最稳的。4.4 升级过程中途断掉网络问题还是本地源路径问题离线升级包从本地 file:// 路径读取理论上不依赖网络但如果你的离线包放在 NFS 或 iSCSI 挂载目录上中途挂载断开dnf 会报 Unable to read consumer identity 或者下载失败。这看起来像网络问题实际上根源在共享存储连接不稳定。我的建议是优先把离线升级包解压到目标机器本地磁盘比如/opt/offline-updates而不是直接挂载目录做源。虽然共享存储能省一份拷贝但升级事务执行时间通常很长中途存储抖动一次整个 dnf 事务就会失败回滚更麻烦。4.5 内核升级后启动卡在 grub 或直接 panic升级包打到一半最常见的高危项就是内核。如果系统中还带了旧内核grub 通常会保留旧内核作为一个启动项所以即使新内核有问题重启时也可以在 grub 菜单里选旧内核进入系统。但有些安全基线会把 grub 菜单调整成“默认第一个启动项直接启动”一旦新内核有问题机器就可能卡住。处理措施是在执行升级前确认/boot分区有足够空间避免内核写入一半就报磁盘满升级完成后reboot前检查 grub 配置里的default值和菜单项顺序。稳妥的操作是升级后先不重启执行grub2-mkconfig -o /boot/grub2/grub.cfg重新生成 grub 配置确保新老内核都在菜单里。万一真起不来进 grub 菜单选旧内核再卸载问题内核包也不迟。4.6 RPM 包依赖排序错乱不要用 rpm -Uvh 直接装这是新手最容易踩的坑。拿到一堆 RPM 文件习惯性rpm -Uvh *.rpm结果 rpm 会按字母序安装包完全不理会依赖关系很容易报“需要被其他包依赖”然后中断。正确姿势永远是配置好本地 repo 后用dnf upgrade让 dnf 来做依赖解析和事务排序。离线包的意义也正在于此它不只是“一堆 RPM 文件”而是一个带元数据的仓库dnf 才能体现价值。5. 离线升级包的扩展应用Docker、桌面环境和常用软件离线包弄通之后你会发现这套思路可以扩展到一个更广阔的领域不只是升级系统任何软件都能用同样的模式离线下发。下面以 Docker 和桌面环境为例讲一下具体做法。5.1 离线安装 DockerRPM 包 镜像 tar热搜词里高频出现“openEuler 安装 docker 更新到 28”这确实是离线场景里最常见的需求之一。在联网中转机上先配好 Docker 相关的 yum 源openEuler 官方 EPOL 里通常有 docker 相关包或者用 Docker 官方源然后抓取 docker 和全部依赖dnf install dnf-plugins-core -y dnf download docker docker-cli containerd.io docker-compose-plugin --resolve --alldeps --destdir/opt/docker-offline抓完之后同样用 createrepo 生成仓库元数据拷到内网机器配置一个独立的 offline-docker.repo然后dnf --disablerepo* --enablerepooffline-docker install docker-ce docker-ce-cli containerd.io -y systemctl enable --now docker要注意的是 Docker 版本迭代快离线包里的版本是快照内网机器无法随手docker pull新镜像。解决方法是把需要的镜像提前导出来docker pull openeuler/openeuler:22.03-lts-sp3 docker save openeuler/openeuler:22.03-lts-sp3 -o openeuler-sp3.tar内网机器上用docker load -i openeuler-sp3.tar导入。把“RPM 包 镜像 tar”放在一起就是一个完整的离线 Docker 交付物这两部分缺一不可。5.2 离线安装桌面环境直接用 Everything ISO 做源头如果内网机器要装图形界面离线包方式依然可行。最简单粗暴的办法是从官方镜像站下载 openEuler 22.03 LTS SP3 Everything ISO挂载后直接用 ISO 里的仓库安装桌面组。mount -o loop openEuler-22.03-LTS-SP3-everything-x86_64.iso /mnt然后在/etc/yum.repos.d/里写一个指向/mnt的 repo启用后执行dnf --enablerepoiso-everything groupinstall GNOME -yopenEuler 的 Everything ISO 里带的软件包比最小化安装多得多GNOME、UKUI、DDE 这些桌面环境都有对应的 group 名称可以用dnf group list查。这个方法比手动下载数百个 RPM 更稳适合一次性部署场景。但对于已经部署好、只想补丁升级的机器最好还是用独立补丁目录而不是反复挂 ISO。5.3 把离线升级包做成周期性维护动作最后聊一个长期使用的心得。离线升级包不要做成“一次性救火”而应该当成周期性维护流程。我现在的做法是每两周或每月在中转机上重新跑一次dnf reposync把更新目录增量同步到内网的“补丁分发机”上然后由分发机统一对内网机器做升级。这样内网机器不会一次性累积几百个补丁风险面小也方便回溯每次变更。增量同步用 rsync 比较合适只传新增和变化的部分rsync -av --delete /data/offline-updates/ /内网挂载路径/offline-updates/但--delete要小心建议先手动对比一下新旧 repodata 里的包数量别把内网还没装的旧包误删掉。如果条件允许每次同步前最好在中转机上跑一次createrepo_c --update让元数据保持最新。我个人的经验是离线升级这件事最怕的不是技术复杂而是“临时处理”的侥幸心态。把抓包目录、repo 文件、GPG 密钥、校验值这些要素固定下来做成标准操作流程后面每次执行都会非常省心。希望这整套流程能帮你少走点弯路。本文还有配套的精品资源点击获取