☰
CentOS离线安装依赖包:精准测绘与原子化部署实战
2026/10/22 10:53:00 网站建设 项目流程

1. 项目概述:为什么离线环境下的依赖包安装是运维人员的“硬核基本功”

在某高校数据中心的一次例行系统升级中,我接手了一台部署在物理隔离网络中的 CentOS 7 服务器——它既没有外网访问权限,也无法挂载任何外部存储设备,唯一可用的介质是一张空白U盘。任务很明确:将一台全新安装的最小化 CentOS 系统,完整升级至生产环境所需状态,包括 Python 3.9、Nginx 1.22、OpenSSL 1.1.1w、以及一整套用于日志分析的 ELK 组件依赖链。这不是简单的yum install能解决的问题,而是一场对 Linux 包管理机制、RPM 依赖图谱、构建工具链和系统底层逻辑的综合实战检验。

“rehat\centos离线安装系统所有依赖包”这个标题看似直白,实则暗含三层关键挑战:第一层是依赖关系的不可见性——yum deplist只能告诉你“需要什么”,却无法自动告诉你“去哪里找”;第二层是包版本的强耦合性——CentOS 7 的 glibc 2.17 与 CentOS 8 的 2.28 完全不兼容,一个包名相同但构建环境不同,就可能引发段错误;第三层是离线环境的零容错性——你只有一次U盘拷贝机会,漏掉任何一个.so文件或perl-libs子包,整个安装流程就会卡死在error: Failed dependencies的报错里,而你连 Google 报错信息的机会都没有。

我之所以把这件事称为“硬核基本功”,是因为它绕不开 RPM 的四元组(name-version-release-arch)校验机制、YUM 的元数据仓库结构(repodata)、以及createrepo工具如何将一堆.rpm文件组织成可被yum识别的本地源。这不是靠背命令就能搞定的活儿,而是要真正理解:当你敲下yum install httpd时,系统其实在后台做了三件事——解析httpd的 Requires 字段、递归检索所有被依赖的包(比如systemd,apr,pcre)、再根据baseurl拼出每个包的完整下载路径。离线场景下,这三步全部要人工完成、手动验证、逐层打包。关键词“rehat\centos”不是指两个发行版混用,而是强调 Red Hat 系生态(RHEL/CentOS/AlmaLinux/Rocky)共享同一套构建规范和 ABI 兼容策略,这意味着你在 RHEL 7 构建的包,只要架构一致(x86_64),就能直接在 CentOS 7 上安装——这是离线方案可行性的底层基石。

适合阅读本文的,绝不是刚学 Linux 的新手,而是已经能熟练配置 Nginx、写 Shell 脚本、甚至会编译过内核模块的中级以上运维或 DevOps 工程师。如果你还在为No package nginx available报错而反复百度,那建议先补一补rpm -qpi和yum repolist的基础用法;但如果你已经经历过在客户机房里,面对一台没联网的服务器,手心冒汗地翻查yumdownloader --resolve帮助文档,那你就是本文最精准的目标读者。这篇文章不讲概念,只讲我在五次真实离线部署中踩过的坑、验证过的路径、以及最终沉淀下来的、可直接复制粘贴执行的完整工作流。

2. 整体设计思路:为什么必须放弃“一键下载所有依赖”的幻想

很多人第一次尝试离线安装时,会本能地搜索“centos 一键下载所有依赖包”,然后找到yumdownloader --resolve这个命令。听起来很美:一条命令,自动拉取目标软件及其全部依赖,打包带走。但实操下来,你会发现它在真实环境中几乎必然失败。原因不在命令本身,而在我们对“依赖”的认知偏差。

2.1 依赖的三重嵌套结构:Runtime、Build、Meta

一个典型的httpd包,在yum deplist httpd输出中会列出几十行依赖项,但这些依赖并非平级存在,而是分属三个完全不同的生命周期层级:

  • Runtime 依赖(运行时依赖):这是yumdownloader --resolve能抓到的部分,比如libapr-1.so.0()(64bit)、systemd-units。它们是程序启动后实际加载的动态库或服务单元,属于“必须安装才能运行”的硬依赖。

  • Build 依赖(构建时依赖):这类依赖在yum deplist中根本不会出现,因为它们只在 RPM 打包阶段起作用。例如httpd的 SPEC 文件中定义了%build阶段需要gcc,make,autoconf,但这些工具在运行httpd时完全不需要。然而,当你试图离线安装一个从源码编译的定制版httpd(比如打了 patch 的版本)时,它的 RPM 包头里可能通过BuildRequires字段声明了openssl-devel >= 1.1.1——这个openssl-devel就是 Build 依赖,yumdownloader默认不会下载它,但如果你后续要重新编译其他组件,就会因缺少头文件而失败。

  • Meta 依赖(元数据依赖):这是最容易被忽略的一层。比如epel-release包本身不提供任何可执行文件,但它向/etc/yum.repos.d/写入了一个.repo文件,从而让yum知道去哪里找nginx。在离线环境中,你不仅需要epel-release-7-11.noarch.rpm这个包,还需要把它安装后生成的 repo 配置内容,手动复制到目标机器的对应目录下,并确保baseurl指向你准备好的本地路径(如file:///mnt/usb/epel)。否则,yum install nginx会直接报No package nginx available,因为它根本不知道 EPEL 源的存在。

提示:yumdownloader --resolve只处理 Runtime 依赖,且默认只下载当前系统架构(uname -m)的包。如果你在 x86_64 主机上为 aarch64 目标机下载,它不会自动识别并切换架构,必须显式指定--archlist=aarch64。

2.2 为什么“全量镜像”方案在实践中不可行

另一个常见误区是:既然单个包依赖复杂,那不如直接下载整个 CentOS Base 和 Updates 仓库的 ISO 镜像?比如CentOS-7-x86_64-DVD-2009.iso。这个想法很直观,但存在三个致命缺陷:

  1. 体积失控:一个完整的 CentOS 7 DVD 镜像约 4.5GB,其中包含超过 8000 个 RPM 包。而你实际需要的可能只是其中 200 个。U盘空间有限,更关键的是,createrepo为整个镜像生成元数据(repodata)需要数小时,且生成的repomd.xml文件巨大,yum解析时内存占用飙升,老旧服务器极易 OOM。

  2. 版本污染风险:DVD 镜像是某个时间点的快照(如 2009 版本),而你的目标系统可能已通过yum update升级到最新内核(如kernel-3.10.0-1160.118.1.el7)。如果你用旧镜像作为源,yum update会强制降级内核,导致系统无法启动。离线环境没有回滚机制,一次降级等于重装系统。

  3. 安全更新缺失:DVD 镜像不含任何 Security Errata(安全公告)对应的更新包。例如 CVE-2021-41773(Apache 路径遍历漏洞)的修复包httpd-2.4.6-97.el7_9.1不在原始 DVD 中,必须单独从 CentOS 官方 Updates 仓库下载。而 Updates 仓库是持续滚动更新的,其 URL 结构为http://mirror.centos.org/centos/7/updates/x86_64/Packages/,无法用固定 ISO 覆盖。

因此,我的设计思路非常明确:放弃“全量”幻想,拥抱“精准外科手术”。核心原则是“三不”——不下载未声明的包、不引入未验证的版本、不依赖未确认的源。具体拆解为四个步骤:

  1. 环境测绘:在一台与目标机完全一致(同版本、同架构、同已安装包集合)的联网机器上,精确测绘出目标软件的完整依赖树;
  2. 包源锁定:为每一个依赖包,确定其唯一、稳定、可追溯的下载来源(官方 Base/Updates/EPEL,或可信第三方仓库);
  3. 增量打包:仅下载测绘结果中列出的包,按源分类存放,并为每个源独立生成轻量级 repodata;
  4. 原子化部署:将 U 盘划分为多个逻辑分区(如/mnt/usb/base,/mnt/usb/epel),在目标机上通过yum-config-manager --add-repo动态挂载,实现“按需启用”。

这个方案的优势在于:总包体积可控制在 200MB 以内(典型 Web 服务栈),createrepo生成元数据耗时小于 30 秒,且每个源的更新可独立进行——今天更新 EPEL,明天更新 Updates,互不影响。

3. 核心细节解析:从测绘到打包的七步实操铁律

离线依赖包的准备工作,本质上是一场精密的“数字考古”。你需要在联网环境中,像考古队员清理文物一样,一层层剥离出目标软件的真实依赖轮廓。下面是我经过五次迭代验证的七步标准流程,每一步都附有原理说明和避坑要点。

3.1 第一步:构建纯净测绘环境(Why:避免污染依赖图谱)

在任意一台联网的 CentOS 7 机器上,不要直接在生产环境测绘。必须创建一个与目标机完全一致的干净沙箱。最佳实践是使用docker启动一个最小化容器:

# 拉取官方 CentOS 7 镜像(确保与目标机 minor version 一致) docker pull centos:7.9.2009 # 启动容器,挂载一个空目录用于存放下载的 RPM docker run -it --rm -v $(pwd)/rpm_cache:/rpm_cache centos:7.9.2009 /bin/bash

进入容器后,首先禁用所有非必要仓库,只保留base和updates:

# 备份原始 repo 配置 mv /etc/yum.repos.d/*.repo /tmp/ # 创建精简版 base.repo cat > /etc/yum.repos.d/base.repo << 'EOF' [base] name=CentOS-$releasever - Base baseurl=http://mirror.centos.org/centos/7/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled=1 [updates] name=CentOS-$releasever - Updates baseurl=http://mirror.centos.org/centos/7/updates/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled=1 EOF

注意:这里baseurl必须使用http://而非https://。某些老旧 CentOS 7 容器的curl或libcurl版本过低,不支持 SNI 或 TLS 1.2,访问https会报Peer's Certificate issuer is not recognized错误,导致yum makecache失败。这不是安全妥协,而是离线部署的现实适配。

3.2 第二步:精确测绘目标软件的 Runtime 依赖(Why:yum deplist是唯一权威来源)

假设我们要部署nginx。执行:

# 清理缓存,确保元数据最新 yum clean all && yum makecache # 获取 nginx 的完整依赖列表(文本格式,便于后续处理) yum deplist nginx | grep 'provider:' | awk '{print $2}' | sort -u > /rpm_cache/nginx_deps.txt

这条命令的输出,就是nginx在当前仓库状态下,所有被声明的 provider 包名。例如:

centos-logos epel-release glibc libcrypt libpcre ...

关键点在于:yum deplist的结果是动态的,它取决于你当前启用的仓库。如果你之前启用了 EPEL,那么nginx的 provider 就是epel-release;如果没启用,yum会告诉你No package nginx available。因此,测绘前必须确保base.repo中已正确配置了所有目标软件所在的源。

实操心得:我曾在一个项目中漏掉了epel-release的测绘,导致离线安装时yum install nginx一直失败。排查了两小时才发现,epel-release包本身也需要被下载并安装,它才是解锁 EPEL 源的“钥匙”。所以,测绘清单里必须包含所有*-release类包。

3.3 第三步:递归测绘所有依赖包的依赖(Why:依赖存在传递性)

上面得到的nginx_deps.txt只是第一层依赖。glibc自身又依赖glibc-common,libpcre依赖pcre,这些都需要被纳入。执行递归测绘:

# 创建一个脚本,自动递归获取所有依赖 cat > /rpm_cache/dep_resolver.sh << 'EOF' #!/bin/bash INPUT_FILE="/rpm_cache/nginx_deps.txt" OUTPUT_FILE="/rpm_cache/all_deps.txt" touch "$OUTPUT_FILE" while IFS= read -r pkg; do if [ -z "$pkg" ]; then continue; fi # 跳过 release 包,它们不依赖其他包 if echo "$pkg" | grep -q 'release$'; then echo "$pkg" >> "$OUTPUT_FILE" continue fi # 获取该包的 provider 列表,并去重追加 yum deplist "$pkg" 2>/dev/null | grep 'provider:' | awk '{print $2}' | sort -u >> "$OUTPUT_FILE" done < "$INPUT_FILE" # 最终去重并排序 sort -u "$OUTPUT_FILE" > "/rpm_cache/all_deps_final.txt" EOF chmod +x /rpm_cache/dep_resolver.sh /rpm_cache/dep_resolver.sh

运行后,all_deps_final.txt就是完整的、无重复的依赖包名列表。注意,这个列表里可能包含kernel、grub2等系统核心包,它们通常不应被离线安装(风险极高),需要人工审查剔除。

3.4 第四步:为每个包名解析出完整 RPM 文件名(Why:yumdownloader需要精确的 name-version-release.arch 格式)

yum deplist只给包名(如glibc),但下载时需要完整文件名(如glibc-2.17-325.el7_9.x86_64.rpm)。这一步必须借助repoquery工具:

# 安装 yum-utils(它提供了 repoquery) yum install -y yum-utils # 为 all_deps_final.txt 中的每个包,查询其最新可用的 RPM 文件名 while IFS= read -r pkg; do if [ -z "$pkg" ]; then continue; fi # --qf 指定输出格式:%{name}-%{version}-%{release}.%{arch}.rpm repoquery --qf "%{name}-%{version}-%{release}.%{arch}.rpm" --pkgnarrow=all "$pkg" 2>/dev/null | head -n1 done < /rpm_cache/all_deps_final.txt | sort -u > /rpm_cache/rpm_list.txt

repoquery的强大之处在于,它能穿透仓库元数据,直接返回Packages/目录下实际存在的文件名。head -n1是为了防止同一个包名在不同仓库(如 base 和 updates)中存在多个版本时,只取最新一个。例如glibc在 base 中是2.17-323,在 updates 中是2.17-325,我们只取后者。

提示:repoquery默认只查询已启用的仓库。如果你的nginx来自 EPEL,必须先在base.repo中添加 EPEL 源,或者单独为 EPEL 创建一个epel.repo并启用它。

3.5 第五步:批量下载 RPM 包并按源分类(Why:避免源冲突,便于后续 createrepo)

现在有了rpm_list.txt,开始下载。但不能一股脑全塞进一个文件夹,必须按来源(base/updates/epel)分开:

# 创建目录结构 mkdir -p /rpm_cache/{base,updates,epel} # 读取 rpm_list.txt,根据包名判断来源并下载 while IFS= read -r rpm; do if [ -z "$rpm" ]; then continue; fi pkg_name=$(echo "$rpm" | cut -d'-' -f1) # 简单规则:以 epel- 开头的,或名字在知名 EPEL 包列表里的,归入 epel if [[ "$pkg_name" == "epel-release" ]] || [[ "$rpm" == *"epel"* ]]; then target_dir="/rpm_cache/epel" elif [[ "$rpm" == *"el7_9"* ]]; then # el7_9 是 updates 的典型 release tag target_dir="/rpm_cache/updates" else target_dir="/rpm_cache/base" fi # 使用 yumdownloader 下载到指定目录 yumdownloader --destdir="$target_dir" "$rpm" 2>/dev/null done < /rpm_cache/rpm_list.txt

这个分类逻辑虽简单,但足够可靠。el7_9是 CentOS 7.9 Updates 仓库的标准 release 标签,epel-release是 EPEL 的入口包,抓住这两个锚点,就能覆盖 95% 的场景。

3.6 第六步:为每个源目录生成轻量级 repodata(Why:yum必须有 repomd.xml 才能识别本地源)

这是离线方案的“临门一脚”。createrepo是yum-utils的一部分,它会扫描目录下的所有.rpm文件,生成repodata/子目录,其中最关键的是repomd.xml——yum就是靠它来索引包的依赖关系的。

# 为每个源目录单独生成 repodata for dir in /rpm_cache/{base,updates,epel}; do if [ -d "$dir" ] && [ "$(ls -A $dir/*.rpm 2>/dev/null)" ]; then echo "Generating repodata for $dir..." createrepo --workers=2 --database --update "$dir" fi done

--workers=2限制并发数,避免在低配虚拟机上卡死;--database启用 SQLite 数据库加速查询;--update表示如果repodata已存在,则只更新变化的部分,极大提升二次打包效率。

注意:createrepo生成的repomd.xml文件里,每个<data>节点的type属性(如primary,filelists,other)必须与yum期望的一致。如果yum报Error: Cannot retrieve repository metadata (repomd.xml) for repository,大概率是repomd.xml中的 checksum 与实际文件不匹配,此时只需删除repodata/目录,重新运行createrepo即可。

3.7 第七步:U盘分区与目录结构规划(Why:物理介质的组织方式决定部署效率)

U盘不是简单地把所有 RPM 拷进去就行。我推荐采用以下分区方案:

分区挂载点用途内容示例
/mnt/usb/baseCentOS Base 源Packages/(所有 base 包)+repodata/
/mnt/usb/updatesCentOS Updates 源Packages/(所有 updates 包)+repodata/
/mnt/usb/epelEPEL 源Packages/(所有 epel 包)+repodata/
/mnt/usb/scripts部署脚本install_all.sh,enable_repos.sh

这样做的好处是:在目标机上,你可以用yum-config-manager --add-repo file:///mnt/usb/base精确启用某个源,而不会因为baseurl=file:///mnt/usb/指向根目录,导致yum错误地将scripts/目录也当作一个源来解析,从而报Cannot find a valid baseurl for repo。

最后,将/rpm_cache/下的base/,updates/,epel/三个目录,完整拷贝到 U 盘的对应分区即可。总大小通常在 150-300MB 之间,一张 4GB 的老式 U 盘绰绰有余。

4. 实操过程详解:在目标离线机上的五步原子化部署

当 U 盘插到那台没有网络的 CentOS 7 服务器上时,真正的考验才开始。部署过程必须像手术一样精准,任何一步出错,都可能导致系统进入半瘫痪状态。以下是我在某金融客户现场实测通过的五步法,每一步都有明确的验证点。

4.1 第一步:挂载 U 盘并验证文件完整性(Why:硬件读取错误是离线部署的第一大杀手)

首先,确认 U 盘被正确识别:

# 查看磁盘列表 lsblk # 假设 U 盘是 /dev/sdb1,创建挂载点并挂载 mkdir -p /mnt/usb/{base,updates,epel,scripts} mount /dev/sdb1 /mnt/usb/base # 验证挂载是否成功,且 repodata 存在 ls -l /mnt/usb/base/repodata/repomd.xml # 应该输出类似:-rw-r--r--. 1 root root 3240 Jan 15 10:23 /mnt/usb/base/repodata/repomd.xml

最关键的验证是检查repomd.xml的完整性。如果ls报No such file or directory,说明createrepo步骤失败,或者 U 盘拷贝时文件损坏。此时不要继续,应立即在测绘机上重新生成repodata并重拷。

提示:lsblk有时无法显示 U 盘,可尝试dmesg | tail -20查看内核日志,确认 USB 设备是否被识别。老旧服务器的 USB 2.0 控制器可能存在兼容性问题,此时可换用 USB 3.0 接口,或在 BIOS 中开启 XHCI Hand-off 选项。

4.2 第二步:动态添加本地仓库(Why:yum-config-manager是最安全的启用方式)

不要手动编辑/etc/yum.repos.d/下的文件。使用yum-config-manager可以确保语法正确,且支持--save参数自动保存:

# 启用 base 源 yum-config-manager --add-repo file:///mnt/usb/base # 启用 updates 源 yum-config-manager --add-repo file:///mnt/usb/updates # 启用 epel 源 yum-config-manager --add-repo file:///mnt/usb/epel # 查看当前启用的仓库 yum repolist enabled # 应该看到 base, updates, epel 三个仓库的状态为 enabled

yum-config-manager --add-repo会在/etc/yum.repos.d/下生成形如generated-repo-XXXX.repo的文件,其内容类似:

[generated-repo-12345] name=added from: file:///mnt/usb/base baseurl=file:///mnt/usb/base enabled=1 gpgcheck=0

注意gpgcheck=0—— 因为我们没有同步 GPG 密钥,离线环境下验证签名不现实。这是权衡安全与可用性的必要妥协,但前提是:你信任测绘机的网络环境,且所有 RPM 都来自官方镜像。

4.3 第三步:构建本地缓存并验证依赖解析(Why:yum makecache是离线部署的“压力测试”)

这一步至关重要,它会触发yum解析所有repomd.xml,构建本地数据库。如果这一步失败,后面所有install都会报错:

# 清理旧缓存,强制重建 yum clean all yum makecache # 验证 nginx 是否能被正确识别 yum list available nginx # 应该输出:nginx.x86_64 1:1.20.1-10.el7.ngx epel # 验证其依赖是否全部可满足 yum deplist nginx | grep 'provider:' | head -10 # 应该能看到 libpcre, openssl 等包名,且它们都来自 file:///mnt/usb/... 的路径

如果yum makecache报错Cannot retrieve repository metadata,请立即检查:

  • /mnt/usb/*/repodata/repomd.xml文件是否存在且非空;
  • U 盘是否以ro(只读)模式挂载,导致yum无法写入缓存;
  • 目标机的glibc版本是否低于测绘机(如测绘机是 7.9,目标机是 7.6),导致createrepo生成的 SQLite 数据库不兼容。

4.4 第四步:执行原子化安装(Why:--assumeyes和--setopt是离线环境的生命线)

现在可以安装了。但绝不能直接yum install nginx,必须加上关键参数:

# 安装 nginx 及其所有依赖,自动确认,跳过已安装包 yum install -y --setopt=tsflags=nodocs nginx # --setopt=tsflags=nodocs 是关键!它告诉 yum 跳过安装所有文档文件(man pages, /usr/share/doc/*) # 这能减少 30% 的磁盘占用,且在服务器环境中,文档几乎从不被查阅

-y参数必不可少,因为离线环境下没有交互终端,yum会卡在Is this ok [y/d/N]:提示上。--setopt=tsflags=nodocs是我从无数次磁盘空间不足的崩溃中总结出的黄金参数——一个python3包的文档目录动辄 50MB,而nodocs模式下,它只安装核心的.pyc文件和二进制。

安装完成后,验证服务状态:

# 检查 nginx 是否安装成功 rpm -qa | grep nginx # 应该输出:nginx-1.20.1-10.el7.ngx.x86_64 # 启动并设为开机自启 systemctl start nginx systemctl enable nginx # 检查端口监听 ss -tlnp | grep :80 # 应该看到 nginx 进程监听 80 端口

4.5 第五步:卸载临时仓库并清理(Why:保持系统清洁,避免未来yum update意外启用离线源)

部署成功后,必须移除临时添加的仓库,否则下次yum update会尝试从 U 盘拉取更新,而 U 盘可能已被拔掉:

# 删除所有由 yum-config-manager 添加的 repo 文件 rm -f /etc/yum.repos.d/generated-repo-*.repo # 卸载 U 盘 umount /mnt/usb/base /mnt/usb/updates /mnt/usb/epel # 清理挂载点 rmdir /mnt/usb/{base,updates,epel,scripts}

至此,整个离线部署流程完美闭环。从 U 盘插入,到nginx服务正常运行,全程不超过 10 分钟,且所有操作均可脚本化,形成标准化交付物。

5. 常见问题与独家排查技巧实录

在五次真实离线部署中,我记录了 17 个高频问题。下面精选 5 个最具代表性的,附上我的第一手排查思路和解决方案。这些问题,90% 的网上教程都不会提,但它们恰恰是让你在客户机房里多待两小时的关键。

5.1 问题一:“Error: Package: xxx requires yyy, but none of the providers can be installed”

现象:yum install报错,提示某个包(如libcurl)需要libssh2,但yum说找不到 provider。

排查思路:这不是包没下载,而是libssh2这个包,可能存在于epel源,但你的测绘环境没启用 EPEL,导致yum deplist没把它列出来。

解决方案:

  1. 在测绘机上,手动启用 EPEL 源:yum install epel-release;
  2. 重新运行yum deplist nginx,确认libssh2是否出现在输出中;
  3. 如果出现,将其加入nginx_deps.txt,重新走一遍七步流程。

独家技巧:用repoquery --whatrequires libssh2可以反向查询哪些包依赖libssh2,快速定位漏掉的上游包。

5.2 问题二:“GPG key retrieval failed: [Errno 14] curl#37 - 'Couldn't open file /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7'”

现象:yum makecache报 GPG 密钥文件不存在。

原因:createrepo生成的repomd.xml中,<data type="primary">节点的<checksum type="sha256">和<open-checksum type="sha256">是基于gpgkey=file:///etc/pki/rpm-gpg/...的路径计算的。但离线机上没有这个文件。

终极解法:在测绘机上,下载并导入 GPG 密钥,然后在createrepo时指定--gpg-key:

# 在测绘机上下载密钥 curl -o /tmp/RPM-GPG-KEY-CentOS-7 http://mirror.centos.org/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7 # 为每个源目录生成 repodata 时,带上密钥 createrepo --gpg-key /tmp/RPM-GPG-KEY-CentOS-7 --workers=2 --database --update /rpm_cache/base

这样,repomd.xml中的gpgkey字段就会指向file:///tmp/RPM-GPG-KEY-CentOS-7,而你只需在离线机上把密钥文件放到/tmp/下即可。虽然麻烦,但一劳永逸。

5.3 问题三:“Transaction check error: file /usr/lib64/libcrypto.so.1.1 from install of openssl-libs conflicts with file from package openssl11-libs”

现象:安装openssl-libs时,与已有的openssl11-libs冲突。

本质:这是 CentOS 7 上著名的 OpenSSL 双版本共存问题。openssl11-libs是 EPEL 提供的 OpenSSL 1.1.x,而系统自带的是 1.0.2。nginx可能同时依赖两者。

安全解法:

  1. 不要强行--force安装;
  2. 查看nginx的Requires字段:rpm -qpR /mnt/usb/epel/Packages/nginx-*.rpm | grep openssl;
  3. 如果它要求openssl11-libs,那就只启用epel源,禁用base源中的openssl相关包;
  4. 在/etc/yum.conf中添加exclude=openssl*,阻止 base 源的 openssl 包被安装。

5.4 问题四:“Could not contact any CDS servers” 或 “Failed to synchronize cache for repo ‘base’”

现象:yum makecache报无法连接 CDS(Content Delivery Server)。

真相:这是yum的一个古老 bug,当baseurl是file://协议时,某些版本的yum会错误地尝试发起 HTTP 请求。这不是网络问题,而是yum的代码缺陷。

绕过方案:在/etc/yum.repos.d/下,手动编辑生成的 repo 文件,将baseurl=file:///mnt/usb/base改为baseurl=file:///mnt/usb/base/(末尾加斜杠)。这个细微差别,能欺骗yum进入正确的本地文件处理分支。

5.5 问题五:U 盘在目标机上识别为只读(Read-only file system)

现象:mount后,ls -l /mnt/usb/base显示所有文件权限为r--r--r--,且createrepo报错Permission denied。

根源:U 盘文件系统是 FAT32,而 FAT32 不支持 Linux 的 Unix 权限位。mount时,内核会默认以ro模式挂载。

可靠解法:

  1. 在测绘机上,将 U 盘重新格式化为 ext4:mkfs.ext4 /dev/sdb1;
  2. 重新拷贝所有文件;
  3. 在离线机上挂载时,显式指定rw:mount -o rw /dev/sdb1 /mnt/usb/base

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询