1. AnolisOS 8.x 上的本地 repo 源究竟在解决什么麻烦我手头这批机器装的是 AnolisOS 8.8机房统一不出网dnf install敲下去界面就卡住转半天甩出一句Cannot download repomd.xml。第一次碰到这种情况的人往往先去 ping 镜像站、改 DNS、翻代理折腾一圈才发现根本不是网络层的事——是这台机器压根没有可达的软件源。这时候最省事也最可靠的做法就是把 AnolisOS 的安装 ISO 当成一个 repo 来用也就是大家常说的本地源。所谓本地源说白了就是告诉包管理器“别去外网找了软件包就在本机某个目录里元数据也在你自己读。”AnolisOS 8.x 的安装镜像是完整的仓库快照里面已经带了repodata元数据目录不需要额外生成。你只要把它挂起来再写一个指向它的.repo文件dnf就能像访问外网源一样装包、查依赖、解决冲突。整个过程不涉及任何网络访问装包速度基本取决于磁盘 IO。这套方案适合谁我列几类典型场景一是完全隔离的内网或者实验环境机器不许出网二是批量部署几十上百台机器每台都去外网拉包既慢又占出口带宽三是做系统实验、考证练习需要一套稳定可控、不会因为镜像站抽风而中断的源四是线上机器出故障需要快速降级或者补装一个依赖包但不敢动外网配置。这几类场景的共性是你要的不是“最新的包”而是“确定能用、随时能用”的包。这里要先纠一个概念上的常见混淆。搜“repo 配置”的时候你大概率会撞到一堆讲 Android 的repo工具、repo sync、Git 与 repo 代码仓库管理优劣对比的文章。那个 repo 是 Google 用来管理多 Git 仓库的 Python 脚本跟 Linux 发行版的软件仓库完全是两码事。你在 AnolisOS 上配置的 repo 是dnf/yum的仓库定义文件后缀.repo放在/etc/yum.repos.d/下。名字撞了而已别被搜索结果带偏。还有一点值得提前说清楚AnolisOS 8.x 是 RHEL 8 系的兼容发行版包管理器本质上是dnfyum只是一层软链接。所以你在网上找到的 CentOS 7 教程里那些yum clean all、yum makecache命令在 AnolisOS 上照样能用只是底层实际执行的是 dnf。但仓库目录结构不一样CentOS 7 的 ISO 里软件包是一个大平铺目录而 RHEL 8 系拆成了BaseOS和AppStream两个仓库。直接照抄 CentOS 7 的教程八成会在baseurl那一行翻车。1.1 外网源失灵的几种真实原因大部分人第一次接触本地源都是被外网源逼的。我把实际遇到过的原因归成四类方便你对号入座。第一类是物理隔离。机房安全策略规定生产网段不允许访问互联网连 DNS 都不通。这种情况下baseurl指向的任何外网地址都会超时报错通常是Curl error (6): Couldnt resolve host或者直接Connection timed out。第二类是镜像站本身的问题。比如你配的是某个第三方镜像它当天在同步上游、临时下线某个仓库、或者证书过期表现就是Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried。这类问题跟你本机毫无关系但你只能干等。第三类是内网 DNS 或者出口策略只放通了部分域名。比如放通了mirrors.aliyun.com但没放通mirrors.cloud.aliyuncs.com你换个源就挂了。排查这种问题非常费时间因为你得一个个域名去试。第四类最隐蔽机器能上网但系统时间不对导致 HTTPS 证书校验失败或者代理环境变量残留在/etc/profile里。这种报错的干扰性最强。不管哪一类本地源的思路都一样——把不确定性彻底消掉。ISO 文件在本地放着不会因为任何外部因素失效这是它最大的价值。1.2 四种本地源方案横向对比动手之前先选方案。我把常见的几种做法列出来你可以按机器规模和维护成本挑。方案做法磁盘占用适合规模维护成本ISO 挂载loop 挂载 ISObaseurl指向挂载点几乎为 0单机、少量机器低换版本换 ISOISO 解压把 ISO 内容解到磁盘目录约 10-20 GB单机、免挂载困扰低但占空间HTTP 共享一台机器挂 ISOhttpd 对外提供主机占空间客户机为 0整个局域网中要管 SELinux 和防火墙reposync 离线镜像联网机器同步全量仓库到磁盘40 GB 起长期使用的内网高要定期同步单机随手用选前两种。给一屋子机器用选第三种。要做成公司内部的标准源长期维护那就得走第四种配合定时任务做增量同步。我个人的习惯是开发调试机器用 loop 挂载省事机房统一部署用 HTTP 源客户端只写一个.repo文件换镜像只改服务端。下面从最基础的挂载开始讲。2. 动手前的准备镜像、目录与挂载点规划准备工作看着简单但有两三个坑会在这里埋下来后面排查起来很痛苦。先把这几件事做掉。2.1 选对 ISO别拿 Boot 镜像来当源AnolisOS 8.x 官方会提供几种镜像常见的是dvd.iso和boot.iso有时叫minimal。只有 DVD 版本里完整带着BaseOS和AppStream两个仓库的软件包Boot 镜像只是一个网络安装引导盘里面没有几个包拿它做本地源会出问题——你能挂载成功、能生成 repo 文件、dnf repolist也显示正常但一装包就报找不到包因为仓库里确实没有。下载完成后强烈建议校验一下校验值sha256sum AnolisOS-8.8-x86_64-dvd.iso把输出和官网公布的 SHA256 对一下。ISO 几十上百 GB 的场景虽然不多但下载中途断流导致文件损坏是很常见的挂载时可能报wrong fs type或者挂上了但目录里文件残缺。提前验一次能省掉后面半天排查。镜像命名里那个8.8就是系统版本号。lsb_release -a或者cat /etc/os-release可以看到本机当前版本。理论上小版本之间可以混用比如 8.6 的源给 8.8 的机器用因为基础包大部分是兼容的但依赖版本可能出现细微差异。生产环境建议保持 ISO 版本和系统版本一致别偷这个懒。2.2 目录规划和空间估算挂载点建议固定在一个专门的目录比如/mnt/iso或者/opt/repo/iso。我不推荐用/media下面的路径因为现代系统里这个目录经常被桌面环境的自动挂载机制和udisks2管着你手动挂上去的东西可能被系统重新挂载或者卸载行为不可预测。用/mnt或者/opt下自己建的目录最干净。空间上loop 挂载本身几乎不占空间它只是在文件系统和 ISO 之间做了一个映射层读取的时候按需从 ISO 文件里取数据。但解压拷贝就不一样了AnolisOS 8 的完整 DVD 解出来普遍在 15 GB 上下你得先确认df -h里目标分区有足够余量。如果只是临时用一次挂载就够了。如果你担心重启后忘记挂、或者嫌每次挂载麻烦可以把挂载写进/etc/fstab这个后面 4.1 节细说。另外提一个细节挂载点目录在挂载之前必须是空目录。如果/mnt/iso里本来有文件你在上面执行挂载原来的内容会被“盖住”——不是删掉只是看不见了直到你卸载。如果那个目录里放着别的东西很容易造成“文件莫名消失”的错觉。2.3 loop 挂载还是解压拷贝怎么取舍两种方式我都用过各有各的适用场景。loop挂载的命令是这样mount -o loop,ro /data/iso/AnolisOS-8.8-x86_64-dvd.iso /mnt/iso-o loop表示使用回环设备-o ro表示只读挂载。加上只读是个好习惯避免手抖往里面写东西——反正你也写不进去ISO9660 文件系统本身就不支持写入。解压拷贝是这样mkdir -p /opt/repo/anolis8 mount -o loop,ro /data/iso/AnolisOS-8.8-x86_64-dvd.iso /mnt/iso cp -a /mnt/iso/. /opt/repo/anolis8/ umount /mnt/iso拷贝完就可以把 ISO 收起来了baseurl指向/opt/repo/anolis8。这种方式的好处是不依赖 loop 设备某些受限容器或者特殊内核环境下挂载可能失败拷贝一份更稳妥坏处是费空间、费时间。我一般的原则是能用挂载就用挂载除非遇到挂载失败的奇怪环境。3. 核心实操把 ISO 变成能正常装包的本地源前面都是铺垫这里是真正的动手环节。整个流程四步挂载、清场、写配置、验证。每一步都有细节我按顺序拆开讲。3.1 挂载 ISO 并确认仓库目录结构先建挂载点、挂载、然后看目录mkdir -p /mnt/iso mount -o loop,ro /data/iso/AnolisOS-8.8-x86_64-dvd.iso /mnt/iso ls /mnt/iso如果一切正常你应该能看到类似这样的输出BaseOS AppStream EFI images isolinux RPM-GPG-KEY-ANOLISOS TRANS.TBL重点确认三样东西BaseOS目录、AppStream目录、以及根目录下的 GPG 公钥文件。这两个目录就是两个独立的仓库每个目录里面都有一层repodata/那里面装着元数据dnf读取的就是它。这里有个特别容易踩的坑目录名大小写。AnolisOS 8 的 ISO 里是BaseOS和AppStream首字母大写。但有些教程或者老版本可能写成小写的baseos、appstream。Linux 文件名区分大小写路径写错了dnf会直接报Failed to synchronize cache for repo。所以千万别凭记忆写ls看一眼再写几秒钟的事。再确认一下元数据确实存在ls /mnt/iso/BaseOS/repodata/ | head能看到repomd.xml、*-primary.xml.gz之类的文件就说明没问题。如果mount报wrong fs type, bad option, bad superblock先检查 ISO 文件是否下载完整回到 2.1 的校验再检查内核是否支持 iso9660后者的概率很低但容器环境里确实遇到过。3.2 备份原有 repo 文件让外网源先安静下来AnolisOS 装完之后/etc/yum.repos.d/里通常已经有一些.repo文件指向官方或者第三方源。这些文件不处理掉dnf每次执行都会去尝试连接它们超时会让所有操作变得极慢最后还可能因为某个源失败而导致整个事务失败。最稳妥的做法是整体移走不要直接删mkdir -p /etc/yum.repos.d/bak mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/之所以是移动而不是删除是因为你可能还要用回外网源或者需要一个参照去看看原来的配置长什么样。等本地源跑通了再决定要不要彻底清掉。如果你只是想临时禁用而不是移走有两种方式。一种是改文件内容把enabled1改成enabled0另一种是用命令批量操作dnf config-manager --set-disabled *注意这里的引号不能省否则 shell 会尝试做通配符展开。不过实话说在离线环境下我更倾向于直接mv走简单粗暴出问题的时候一目了然——目录里就剩我自己写的那一个文件还能有什么问题。3.3 写一个能用的 local.repo逐行拆解新建文件/etc/yum.repos.d/local-anolis8.repo内容如下[local-BaseOS] nameAnolisOS 8 - BaseOS (Local ISO) baseurlfile:///mnt/iso/BaseOS enabled1 gpgcheck1 gpgkeyfile:///mnt/iso/RPM-GPG-KEY-ANOLISOS [local-AppStream] nameAnolisOS 8 - AppStream (Local ISO) baseurlfile:///mnt/iso/AppStream enabled1 gpgcheck1 gpgkeyfile:///mnt/iso/RPM-GPG-KEY-ANOLISOS看着简单每行都有讲究我逐条解释。[local-BaseOS]是仓库 ID方括号里的内容在整个配置里必须唯一。你可以叫任何名字但一旦定了后面用--enablerepo、--disablerepo参数时就要用这个名字。我习惯加个local-前缀一眼就能区分本地源和外网源。name是显示名dnf repolist的时候会打出来。写清楚用途方便以后你自己或者同事看到时知道这是干嘛的。baseurl是核心。这里必须用file://协议而且是三个斜杠——file:///mnt/iso/BaseOS。两个斜杠加一个路径会被解析成主机名实际含义完全不同。三个斜杠的意思是“本机根目录开始”后面跟绝对路径。这个点看起来低级但我见过不止一个人栽在这上面报错信息还很含糊只说找不到源。如果换成局域网 HTTP 源这里就写baseurlhttp://10.0.0.10/anolis8/BaseOS两个斜杠因为是真正的网络协议。enabled1表示默认启用。想临时关掉改成 0 即可。gpgcheck1表示校验 RPM 包签名。这是安全建议尤其在生产环境。对应的gpgkey必须指向公钥文件AnolisOS 的 ISO 根目录下一般叫RPM-GPG-KEY-ANOLISOS。你可以先ls /mnt/iso | grep -i gpg确认下实际文件名不同小版本命名可能略有差异。如果你在实验环境、纯粹图快把gpgcheck设成 0 也能用包照装。但我要提醒一句关掉校验意味着任何被篡改过的 RPM 都会被无脑装进去。内网环境虽然风险低但没必要省这两行配置。还有一个变量要说明不要在本地源里用$releasever和$basearch。那是给外网镜像站用的模板变量会被替换成 8、x86_64 之类的值。本地源的路径是写死的用变量反而会拼出一个不存在的路径。很多从 CentOS 8 教程抄来的配置会带上这些变量在本地源场景下就是纯粹的错误来源。3.4 刷新缓存并验证别急着装大件配置写完先把脏缓存清掉再重建dnf clean all dnf makecachednf clean all会清掉/var/cache/dnf下所有缓存的元数据。这一步很重要因为之前可能残留了外网源的元数据不清干净可能出现“源列表变了但包列表还是旧的”这种诡异状态。dnf makecache会去读取本地源的元数据并缓存。如果配置正确输出会是每个仓库一条Metadata cache created。如果这里报错说明问题就在配置本身别往下走先解决问题。然后看仓库列表dnf repolist正常的输出类似repo id repo name local-BaseOS AnolisOS 8 - BaseOS (Local ISO) local-AppStream AnolisOS 8 - AppStream (Local ISO)两个仓库都在status没报错就成功了一大半。最后做一次真实装包验证。选一个小包比如tree或者lsofdnf install -y tree rpm -q tree装上了说明整条链路完全通畅。也可以试一下查询类命令dnf provides */nginx dnf list available | wc -l如果dnf provides能正确返回包名和所属仓库说明元数据索引完整可用。一个很实用的临时切换技巧假如你不想动任何配置文件只是想临时从本地源装一个包可以这样dnf --disablerepo* --enablerepolocal-BaseOS,local-AppStream install -y tree前提是local-anolis8.repo文件已经存在enabled设成 0 也行。这个用法的价值在于你可以保留外网源配置平时走外网关键时刻用本地源救急两套配置互不干扰。4. 让本地源更耐用开机自动挂载与局域网共享单机配好只是第一步。实际生产里你会遇到“重启之后本地源失效了”和“几十台机器都要配一遍”这两个问题。这一节解决它们。4.1 写进 fstab避免重启后挂载丢失手动mount的挂载在重启后就没了。/mnt/iso变成空目录dnf立刻报Failed to synchronize cache而且报错信息不会明确告诉你“源没挂载”只说不下载元数据排查起来要愣一下。解决方法是在/etc/fstab里加一行/data/iso/AnolisOS-8.8-x86_64-dvd.iso /mnt/iso iso9660 loop,ro,nofail 0 0字段说明第一列是 ISO 文件路径第二列是挂载点第三列是文件系统类型iso9660第四列是挂载选项。loop是要的告诉系统这是回环文件ro只读nofail强烈建议加上含义是“如果这个挂载失败不要阻止系统启动”。想象一下 ISO 文件被误删或者磁盘挂了没有nofail的话系统可能直接进入紧急模式进不了正常启动流程只能去单用户模式手动改 fstab非常麻烦。加完之后不要急着重启验证先执行umount /mnt/iso mount -a mount | grep /mnt/isomount -a会挂载 fstab 里所有没挂的东西。能正常挂上说明配置对了重启也不会有问题。如果你更习惯用 systemd 的方式管理也可以写一个 mount unit# /etc/systemd/system/mnt-iso.mount [Unit] DescriptionAnolisOS ISO loop mount [Mount] What/data/iso/AnolisOS-8.8-x86_64-dvd.iso Where/mnt/iso Typeiso9660 Optionsloop,ro [Install] WantedBymulti-user.target文件名必须和挂载路径严格对应/mnt/iso对应mnt-iso.mount这是 systemd 的命名规则。然后systemctl daemon-reload systemctl enable --now mnt-iso.mount。两种方式都行我一般图省事用 fstab因为改起来快。4.2 用 httpd 把一个本地源变成整层楼的源机器一多逐台挂 ISO 就很不划算。这时候挑一台机器做源服务器装个 httpd把挂载目录暴露出去其他机器只写一个.repo文件就能用。服务端步骤dnf install -y httpd systemctl enable --now httpd然后有两种做法。第一种是 bind mount 到网站根目录mkdir -p /var/www/html/anolis8 mount --bind /mnt/iso /var/www/html/anolis8bind mount 也是重启即失效同样要写 fstab写法是mount --bind那套或者用 systemd unit。好处是内容直接落在网站目录下不用改 httpd 配置。第二种是加一个 Alias 配置指向/mnt/iso# /etc/httpd/conf.d/anolis-repo.conf Alias /anolis8 /mnt/iso Directory /mnt/iso Options Indexes FollowSymLinks Require all granted /Directory推荐第二种因为挂载点可以变配置文件不用跟着动。SELinux 是这里最容易翻车的地方。如果 SELinux 处于 enforcing 状态httpd 默认读不了/mnt下的内容表现是浏览器或者客户端访问返回 403/var/log/httpd/error_log里能看到Permission denied。两种处理方式我更推荐改上下文而不是关 SELinuxchcon -Rt httpd_sys_content_t /mnt/iso或者在挂载时就指定上下文mount -o loop,ro,contextsystem_u:object_r:httpd_sys_content_t:s0 \ /data/iso/AnolisOS-8.8-x86_64-dvd.iso /mnt/iso顺便说一句直接setenforce 0关掉 SELinux 图省事在一台要给整个网段提供服务的机器上是很糟糕的做法。改上下文就一行命令没必要冒这个风险。防火墙别忘了放行 HTTPfirewall-cmd --permanent --add-servicehttp firewall-cmd --reload服务端验证curl -I http://127.0.0.1/anolis8/BaseOS/repodata/repomd.xml返回 200 就说明服务通了。客户端机器上只需要写[anolis8-http] nameAnolisOS 8 Local Mirror baseurlhttp://10.0.0.10/anolis8/BaseOS enabled1 gpgcheck0 [anolis8-http-appstream] nameAnolisOS 8 Local Mirror AppStream baseurlhttp://10.0.0.10/anolis8/AppStream enabled1 gpgcheck0注意这里我写了gpgcheck0。原因是客户端机器上不一定导入了 AnolisOS 的 GPG 公钥如果gpgcheck1而没导入 key装包会报Public key for xxx.rpm is not installed。想保留校验的话把公钥拷到每台机器然后rpm --importrpm --import /path/to/RPM-GPG-KEY-ANOLISOS内网环境我通常还是会导入 key、把gpgcheck打开多一步操作换个安心。4.3 createrepo_c 和 reposync自建仓库与离线镜像做到上面这一步你已经能用官方 ISO 里的包了。但实际运维中经常需要装 ISO 里没有的东西——公司内部的 RPM 包、第三方工具、特定版本的软件。这时候就得自己建仓库。createrepo_c就是干这个的dnf install -y createrepo_c mkdir -p /var/www/html/custom # 把你自己攒的 rpm 包丢进这个目录 cp /data/rpms/*.rpm /var/www/html/custom/ createrepo_c /var/www/html/customcreaterepo_c会扫描目录里所有 RPM提取依赖信息生成repodata/目录。之后这个目录就变成一个合法的仓库了。客户端加一段配置就能用。注意每次往目录里新增或删除 RPM都必须重新执行一次createrepo_c --update /var/www/html/custom否则新包不在索引里dnf看不到。这个坑我踩过当时放了包进去死活装不上纠结了半小时才想起来没更新元数据。如果你手上有一台能出网的机器想给内网做一份完整镜像用reposync更合适dnf install -y dnf-plugins-core dnf reposync --repoidlocal-BaseOS --download-path/data/mirror --download-metadata dnf reposync --repoidlocal-AppStream --download-path/data/mirror --download-metadata--download-metadata会把仓库的元数据一起拉下来这样拷到内网机器上直接就能用不需要再createrepo_c。如果不带这个参数你就得自己对下载目录重新生成一次元数据。全量同步 AnolisOS 的两个仓库磁盘占用大概在 40 GB 上下做之前先看看空间。同步完把/data/mirror通过 httpd 暴露出去就成了一个完全自主可控的内网源比挂 ISO 灵活得多也能把多个版本的包放在一起。5. 常见报错与排查速查下面这些报错我基本都在实际环境里见过。按现象归类配上排查思路遇到问题直接对照着走。5.1 baseurl 报错族的统一排查思路Cannot find a valid baseurl for repo: base/7/x86_64这个报错在搜本地源的时候出现频率极高。注意看仓库名base/7/x86_64——这是 CentOS 7 的仓库 ID说明搜到这个问题的人大多在折腾 CentOS 7。在 AnolisOS 8 上对应的报错会变成Cannot find a valid baseurl for repo: local-BaseOS之类仓库名是你自己定义的。不管是哪个发行版这个报错的根因只有三种。第一种baseurl指向的路径不存在。这是最常见的。检查顺序路径写没写错大小写、三个斜杠、挂载点还在不在mount | grep iso、目录里有没有repodatals /mnt/iso/BaseOS/repodata。三个都确认一遍问题基本就定位了。第二种网络不可达。如果baseurl是 HTTP 地址先在服务器上curl -I一下那个地址看能不能通。DNS 解析、防火墙、目标服务是否在跑逐层往下查。第三种baseurl这一行被注释掉了或者变量替换出了错。带$releasever的写法在某些环境下会替换成空字符串拼出来的 URL 就是畸形的。打开文件肉眼过一遍两秒钟的事。顺带说一下搜索体验上的一个坑你搜repo相关报错的时候很容易撞到一大堆无法找到来自源 nvlddmkm 的事件 ID 153/0/14 的描述这种内容。那是 Windows 上 NVIDIA 显卡驱动掉线的事件日志跟 Linux 软件仓库没有任何关系。同一个“源”字被搜索引擎混在一起了。看到这类标题直接跳过别浪费时间。5.2 GPG、元数据和缓存类报错Public key for tree-1.7.0-15.el8.x86_64.rpm is not installed——签名校验没过。原因是你开了gpgcheck1但没有导入对应的公钥。解决rpm --import /mnt/iso/RPM-GPG-KEY-ANOLISOS rpm -qa gpg-pubkey | grep -i anolis # 确认导入成功导入之后重跑安装命令即可不需要重新清缓存。Failed to download metadata for repo local-BaseOS: Cannot download repomd.xml——元数据读不到。在本地源的语境下99% 是挂载掉了。mount | grep /mnt/iso一看便知。剩下 1% 是权限问题/mnt/iso及上层目录的权限让 dnf 进程读不了比如/mnt被改成了 700。可以sudo -u nobody ls /mnt/iso/BaseOS模拟一下非特权用户的读取。Error: Failed to synchronize cache for repo local-AppStream——同样是元数据问题但要多查一步AppStream这个目录在你的 ISO 里到底叫什么。有些镜像版本目录名不一样或者你只写了 BaseOS 忘了写 AppStream 这一段。还有一类状态类的诡异问题改了.repo文件但dnf的行为没变化。这通常是缓存没清。养成习惯改完 repo 配置先dnf clean all再操作。/var/cache/dnf里的旧元数据会被优先使用导致你以为新配置没生效其实只是缓存没刷新。5.3 常见问题速查表现象最可能的原因快速验证命令处理方式Cannot find a valid baseurl路径错或未挂载mount | grep iso修正 baseurl 或重新挂载Cannot download repomd.xml挂载丢失或网络不通ls /mnt/iso/*/repodata恢复挂载或排查网络Public key ... is not installed公钥未导入rpm -qa gpg-pubkeyrpm --import导入改配置后行为无变化dnf 缓存未刷新dnf clean all后重试清缓存并重建dnf命令卡很久才报错外网源仍在启用dnf repolist移走或禁用外网 repoHTTP 源返回 403SELinux 上下文不对ls -Z /mnt/isochcon -Rt httpd_sys_content_t新放进的自建包搜不到元数据未更新ls /var/www/html/custom/repodatacreaterepo_c --update重启后本地源失效挂载未持久化mount | grep iso写入 fstab 并加 nofail一个通用的排查顺序我一般这么走先mount确认挂载再ls确认路径和 repodata然后dnf repolist -v看仓库解析出来的baseurl到底是什么最后curl或ls直接访问那个地址。这四步走下来98% 的问题都能定位。dnf repolist -v这个命令特别值得推荐它会打出每个仓库的完整Repo-baseurl、Repo-expire、还有缓存状态。很多时候你以为是配置写错了一看输出发现baseurl被解析成了完全没想到的值问题当场就清楚了。6. 一些实际用下来才知道的细节前面是标准流程这一节是我在反复折腾中攒下来的经验属于文档里不会写、但真能省事的东西。6.1 小版本升级和 ISO 更换的处理顺序系统从 8.6 升到 8.8 之后老的 ISO 源其实还能用但如果你想换新 ISO顺序很重要。正确的做法是先把新 ISO 放到磁盘上校验通过然后卸载旧挂载改 fstab 里的路径挂新的接着dnf clean all dnf makecache最后随便装个包验证一下。反过来操作也就是先卸载旧挂载再去准备新文件中间会有一段时间本地源完全不可用。如果这时候恰好有个自动化脚本在跑dnf install就会直接失败。看起来是小事但在批量运维的机器上这种窗口期引发的偶发失败非常难查。还有一点如果新旧 ISO 的文件名不同很可能因为版本号在文件名里你只改了 fstab 里的路径.repo文件里的baseurl指向挂载点/mnt/iso是不变的所以不需要动。这也是为什么我推荐baseurl指向一个固定的挂载点而不是直接指向 ISO 解压目录——换版本的时候改动最小。6.2 AppStream 的模块流别被 module 命令绕晕AnolisOS 8 的 AppStream 仓库里有 module 的概念这是 RHEL 8 系引入的东西。某些软件比如特定版本的 nginx、nodejs、php被打包成模块流装的时候有两种方式直接dnf install nginx系统会选一个默认流或者先dnf module list nginx看有哪些流再dnf module enable nginx:1.20指定版本再装。本地源对模块的支持是完整的因为repodata里本身就带着模块元数据。但有个问题要注意如果本地源的 AppStream 和 BaseOS 版本不匹配比如 BaseOS 是 8.8 而 AppStream 是 8.6dnf module list可能列出一些依赖关系对不上的流装的时候报冲突。所以我在 2.1 节强调版本要一致模块化的软件包就是最容易出问题的地方。排查模块相关问题用dnf module list dnf module info nginx dnf repoquery --repolocal-AppStream --whatprovides nginx第三条能明确告诉你某个包在哪个仓库里比瞎猜快得多。6.3 几条自己踩出来的经验第一条别把/etc/yum.repos.d弄得太乱。我见过一些机器上躺着十几个.repo文件有的是别人临时加的有的是安装某个软件时自动塞进来的有的文件名还完全看不出用途。结果就是dnf每次操作要遍历所有仓库慢得离谱出了问题也不知道是哪个源惹的。我的习惯是只保留当前实际需要的源其他全部mv到bak目录并在文件名里加上日期比如bak/CentOS-Base.repo.20240115。以后想找回来也方便。第二条给源配置文件写注释。.repo文件是支持#注释的。在文件头写清楚这个源来自哪个 ISO、什么版本、什么时候配的、谁配的。这在团队协作里价值极大。半年后有人在这台机器上排查问题看到一句# 2024-01 AnolisOS 8.8 DVD 本地源联系人xxx能省掉一堆沟通成本。第三条验证速度别只验证能用。本地源配好之后装个小包的时间应该在秒级。如果你感觉dnf还是要卡一两秒才出结果八成是某个外网源还在启用着哪怕它配置里enabled0某些情况下dnf仍会去做一些检查。用dnf repolist -v看看到底有几个仓库在参与顺便看下Repo-expire的值。本地源可以把元数据过期时间设得比较长比如在.repo里加一行metadata_expirenever因为 ISO 内容基本不会变没必要反复去校验。这个小改动能让dnf的响应快一截。第四条给 ISO 文件做个备份或者记录来源。我遇到过 ISO 被清理脚本误删结果本地源全线失效的情况。文件不大不小十几 GB放在一个专门的数据目录里不要跟临时下载文件混在一起路径写进 fstab 之前想清楚这个位置会不会被别人动。最后分享一个我觉得最实用的组合用法日常保留外网源配置但enabled0本地源常开。需要装外网才有的包时临时用--enablerepo指向外网源外网不通时本地源随时兜底。两套配置共存互不干扰机器无论在哪张网里都能装包。这个组合我用了两年多几乎没再因为“装不上包”这种问题耽误过事。