机房里有几台麒麟服务器,网络是物理隔离的,每次打补丁都得拿U盘来回拷rpm包,时间久了谁都想换个活法。最省事的思路其实很朴素:找一台能连外网的 Kylin v10 x86_64 机器,把整个 Yum 源里的安装包一次性同步到本地指定目录,再打包带进内网,配成本地源,从此装什么都是一个命令的事。听着简单,真上手才发现坑不少——磁盘空间没算准、reposync 参数写错目录嵌套了一层、下完包忘了生成元数据导致本地源用不了。这篇就把"Kylin v10 x86_64 系统下载整个 Yum 源的所有安装包到本地指定目录"这件事从头到尾讲清楚,包括参数为什么这么选、空间怎么预估、踩过的坑怎么绕开。不管你是刚开始接触麒麟运维的新手,还是已经搞过 CentOS 本地源的老手,都能从里面找到能直接抄的步骤。
1. 麒麟 V10 的仓库体系与"整源拉取"到底解决什么问题
1.1 为什么会有把整个源搬到本地的需求
先说清楚这个操作存在的理由,不然很容易被人当成"没事找事"。银河麒麟高级服务器操作系统 V10(Kylin Linux Advanced Server V10)大量部署在政务、金融、能源这类内网环境里,物理隔离是硬要求。但这些机器照样要装 JDK、要补安全漏洞、要部署 MySQL 和中间件,每次都用rpm -ivh单个安装包手动装,依赖关系能把人逼疯——A 依赖 B,B 又依赖 C 的特定版本,一层层查下去,装个 fluent-bit 能折腾一下午。把整个 Yum 源同步到本地,本质上是把"依赖求解"这件事交还给包管理器,内网机器只要指向本地源,yum install照样能用,依赖自动补齐,这才是真正省事的地方。
另一个场景是批量部署。几十上百台机器同时上线,如果每台都去外网拉包,带宽扛不住,速度也慢。先在一台机器上把源同步下来做成离线仓库,再通过内网文件服务分发,所有节点都从本地拉,速度快、可控、还不怕外网源哪天挂了。这就是为什么"整源拉取"在麒麟运维里是个高频动作,而不是个花哨的技巧。
1.2 麒麟 V10 的仓库文件和 CentOS 不像是一回事
很多从 CentOS 转过来的人第一反应是去改/etc/yum.repos.d/CentOS-Base.repo,结果发现根本没有这个文件。Kylin V10 虽然底层是 RPM 那一套,包管理器也是 dnf(yum 是它的兼容封装),但仓库配置和命名完全走自己的体系。典型的仓库文件会叫kylin_x86_64.repo,里面定义的仓库 ID 长这样:ks10-adv-os、ks10-adv-updates、ks10-adv-addons。这几个 ID 是你后面 reposync 命令里-r` 参数要填的值,填错了会直接报"找不到仓库"。
这些仓库的 baseurl 一般指向麒麟官方的更新服务器,路径里带$basearch变量,在 x86_64 机器上解析出来就是 x86_64。这里有个容易忽略的点:ARM 架构的麒麟用的是kylin_aarch64.repo,仓库里的包和 x86_64 完全不通用。所以别人分享的同步脚本,如果没注意架构,直接拿来用会拉错架构的包,装到机器上要么装不上,要么运行报错。
提示:动手前先
ls /etc/yum.repos.d/看清楚本机到底有哪几个 repo 文件,再yum repolist看生效的仓库 ID,这两步能帮你避开后面大半的"仓库不存在"报错。
1.3 动手前必须锁死的三个前提
第一个是磁盘空间。一个完整的 Kylin V10 x86_64 系统源,包含基础包、更新包、附加包,加起来动辄几十 GB,具体取决于你启用了几个仓库。如果你只同步 os 和 updates 两个,大概 15 到 30 GB;如果连 addons、SP 补丁包一起拉,50 GB 都不一定够。空间没算够,下到一半磁盘满了,前面下的全白费。
第二个是网络稳定性。整源同步是个长时间任务,几个 GB 甚至几十 GB 的数据要连续传输,中间断一次就可能要重来。同步前最好确认目标机器到源服务器的网络通畅,别在同步过程中还要去处理网络抖动。
第三个是版本对应。Kylin V10 有 SP1、SP2、SP3 等多个版本,不同版本的仓库地址和包内容不一样。你得先确认自己的机器是哪个 SP 版本,再决定同步哪个源,不然会出现"本地源里的包和系统版本对不上,装上去依赖冲突"的情况。
2. 环境核查:把版本、架构和当前仓库摸清楚
2.1 用两条命令双重确认系统版本
麒麟有个自己的版本查看命令叫nkvers,这个命令在别的发行版上没有,输出信息比os-release更贴合麒麟的命名习惯。实际操作里我习惯两条都跑一遍,交叉确认:
cat /etc/os-release nkvers uname -mos-release里重点看VERSION和VERSION_ID两行,会标明类似 "Kylin Linux Advanced Server release V10 (Lance)" 这样的信息。nkvers会更详细地列出内核、SP 版本号。uname -m返回x86_64就说明架构没问题,如果是aarch64那就得换 ARM 的源,整篇的操作思路一样但仓库 ID 不同。
为什么要这么较真?因为麒麟的 SP 版本更新频繁,SP1 和 SP3 的包里有些组件版本差异很大,如果你拿 SP1 的源给 SP3 的机器用,某些库的依赖会解不开。确认清楚版本,后面的同步目标才有意义。
2.2 列出当前启用的仓库并记录仓库 ID
yum repolist -v这个命令会输出每个仓库的 ID、名称、包数量、baseurl。把里面 "Repo-id" 那一列记下来,这就是你 reposync 时要用的-r值。同时看一眼 "Repo-status" 是不是 enabled,如果某个仓库是 disabled 状态,reposync 默认也同步不了它,需要加--enablerepo显式打开。
如果你想搞明白 baseurl 具体指向哪里,可以打开仓库文件直接看:
cat /etc/yum.repos.d/kylin_x86_64.repo重点关注 baseurl 里的路径结构。这个路径决定了 reposync 下载下来的目录层级,后面配置本地源时 baseurl 要指向 repodata 所在的目录,路径错了本地源就识别不到。我见过有人把本地源 baseurl 写成file:///data/repo/,但实际包的元数据在file:///data/repo/ks10-adv-os/,差一层目录,结果yum makecache一直报 "Cannot find a valid baseurl"。
2.3 空间预算:别等磁盘满了才后悔
在真正开跑之前,先做个空间估算。有两个办法:
第一个是看yum repolist -v输出里的 "Repo-size" 字段,它会给出每个仓库里包的总体积估算。虽然不一定百分百准,但作为参考足够。
第二个是去看源的repodata目录,里面有primary.xml.gz之类的元数据文件,解压后能算出总大小,不过这个操作略麻烦,一般人用第一个办法就够了。我给个经验参考值:
| 仓库类型 | 大致体积(x86_64) | 说明 |
|---|---|---|
| os(基础包) | 8 - 15 GB | 系统核心包,必下 |
| updates(更新包) | 5 - 20 GB | 随补丁累积增长 |
| addons(附加包) | 1 - 5 GB | 视业务需要 |
| 全部启用仓库合计 | 30 - 60 GB | 留足空间保险 |
记住,同步过程中除了包本身,还要预留一部分空间给临时文件,所以建议最终目录所在分区至少留出估算体积的 1.3 倍。图省事的做法是直接挂一个大盘到/data,所有离线源都往那儿放。
df -h /data看 Avail 那一列,心里有数了再继续。
3. 工具链准备:reposync 与 createrepo 从哪来
3.1 reposync 的归属:yum-utils 还是 dnf-plugins-core
这是第一个容易迷糊的地方。reposync 不是一个独立命令,它属于插件包。在比较老的系统上它在yum-utils里,在较新的 dnf 体系里它在dnf-plugins-core里。Kylin V10 用的是 dnf 作为底层,yum 是它的兼容命令,所以实际操作里我更倾向直接用 dnf 来装:
dnf install -y dnf-plugins-core createrepo装完之后验证一下命令是否可用:
reposync --help createrepo --help如果reposync --help能正常输出参数列表,说明装好了。这里有个小细节:dnf 版本和 yum-utils 版本的 reposync 参数不完全一样,比如 dnf reposync 支持--download-metadata,而某些老版本的 yum reposync 用-m、--downloadcomps。所以看清楚--help的输出,以本机实际支持的参数为准,别照搬网上旧教程的参数。
注意:如果两个包的版本对不上(比如用 yum 装了老的 yum-utils,又用 dnf 装了 dnf-plugins-core),可能出现 reposync 命令冲突或行为不一致。建议统一用一个包管理器安装,别混着来。
3.2 安装过程中可能遇到的依赖问题
正常情况下dnf install dnf-plugins-core createrepo一把过。但如果你的机器本身还没有配好可用的源,这一步就会失败,报 "没有可用的软件包" 之类的错误。这时候得先确认外网源能连通:
yum repolist yum makecache curl -I <你的源baseurl>curl能返回 200 就说明网络到源服务器没问题,makecache成功就说明元数据能拉下来。如果这两步都过不了,那问题出在网络或源配置,先把这关过了再谈同步整源。
还有一种情况是 gpgcheck 导致的失败。有些环境的源开了签名校验,而本机没有对应的公钥,安装插件包时会报签名验证不通过。临时解决是加--nogpgcheck,但这是权宜之计,正规做法是导入正确的 GPG 公钥。
3.3 用 --help 先摸清参数支持情况
这一步看着多余,实则能省很多时间。因为不同版本的 reposync 参数差异实实在在存在,比如参数名、缩写、是否支持并行下载都可能不一样。我一般会重点确认这几个参数有没有:
-p/--download-path:指定下载根目录,这个必须有。-r/--repoid:指定仓库 ID,多仓库可以写多个。-n/--newest-only:只下最新版本,避免存一堆老包。--download-metadata:是否下载元数据,决定你后面要不要重新 createrepo。--norepopath:控制是否把仓库名作为子目录,这个参数坑过一次,后面细说。
把本机--help输出过一遍,对参数心里有底,写命令的时候就不会瞎猜。
4. 用 reposync 把整个 Yum 源拉到本地目录
4.1 从单仓库到多仓库:命令的层层拆解
先建好目标目录,别指望 reposync 帮你全自动创建多层目录:
mkdir -p /data/kylin-repo最小可用的单仓库同步命令长这样:
reposync -r ks10-adv-os -p /data/kylin-repo/这条命令的意思是:把ks10-adv-os这个仓库的所有包,下载到/data/kylin-repo/目录下,并且会在里面自动建一个以仓库 ID 命名的子目录,也就是/data/kylin-repo/ks10-adv-os/。这个"自动建子目录"的行为就是--norepopath要控制的东西,默认是带仓库名子目录的。
如果你要一次性同步多个仓库,-r可以写多个:
reposync -r ks10-adv-os -r ks10-adv-updates -p /data/kylin-repo/这样会在/data/kylin-repo/下生成ks10-adv-os和ks10-adv-updates两个子目录,各自独立。这种目录结构最清晰,后面配本地源时一个仓库对应一个 baseurl,管理起来方便。
4.2 关键参数逐个讲清楚为什么这么用
光给命令不解释,等于没讲。逐个拆:
-p /data/kylin-repo/指定下载路径。选这个路径有两个考虑,一是空间够大,二是路径深、容易被记住和备份。千万别选/root或者/tmp,前者的系统盘往往空间有限,后者重启就可能被清空,几十 GB 的包丢一次能让人捶胸。
-n(newest-only)这个参数要不要加,取决于你的用途。如果本地源只是给系统打补丁、装应用用,那加上-n只保留每个包的最新版本就够了,能省下大量空间,一个仓库可能从 20 GB 降到 8 GB。但如果你需要在本地源里保留历史版本(比如回滚用),那就别加。我一般正式环境不加,测试环境加,看情况。
--download-metadata表示连仓库的元数据一起下。这个和后面要不要 createrepo 直接相关:如果你用了这个参数,下载下来的repodata目录可能是现成的,理论上可以直接当源用;但为了稳妥,实践里我还是习惯重新 createrepo 一次,避免元数据和实际下载的包不匹配(因为-n会剔掉老包,但元数据里还记着那些老包)。
-a x86_64显式指定架构。虽然本机是 x86_64 时默认就对了,但显式写出来更安全,尤其在脚本里,避免误跑到别的架构机器上。
我的常用组合是:
reposync -r ks10-adv-os -p /data/kylin-repo/ -n --download-metadata4.3 断点续传与失败重试的处理思路
reposync 本身对已下载的文件有断点续传能力——再次执行时,已经下好且完整的包会被跳过,只下缺的。这个特性非常有用,意味着中途断了不用慌,重新跑一遍就行。
但要注意一个坑:如果某个包上次下载到一半被中断,留下了一个不完整的.rpm文件,reposync 再次运行时可能因为文件已存在就跳过了,结果你带着一个损坏的包进了本地源,装的时候报校验失败。稳妥的做法是,每次重跑前检查一下有没有零字节或者体积明显偏小的 rpm 文件:
find /data/kylin-repo -name "*.rpm" -size -1k把这类可疑文件删掉再重跑。养成这个习惯,能避免很多"莫名其妙装不上"的问题。
对于网络超时导致的失败,可以结合timeout命令和循环重试来加固,或者写个简单的重试脚本:
for i in 1 2 3; do reposync -r ks10-adv-os -p /data/kylin-repo/ -n --download-metadata && break echo "第 $i 次失败,10 秒后重试" sleep 10 done4.4 大仓库同步到底要多久,怎么提速
整源同步的耗时不光看包多大,更看源服务器的限速和网络带宽。实测下来,如果是从官方源直接拉,速度可能被限制在几百 KB 到几 MB 每秒,一个 20 GB 的仓库可能要跑好几个小时甚至一整晚。这时候有几个提速思路:
第一,换更近的镜像源。很多第三方镜像站(清华、阿里等)对麒麟或者兼容的 RPM 源有加速,速度能比官方源快不少。注意只有仓库内容和你要的麒麟版本兼容时才能用,别乱换导致包版本错乱。
第二,多个仓库并行拉。因为单个 reposync 进程基本是串行的,你可以开多个终端,每个 terminal 同步一个仓库,虽然还是共享带宽,但对源服务器来说并发连接有时反而能提升总吞吐。
第三,避开高峰期。白天源服务器负载高,晚上速度往往更稳。这种活儿安排在夜里跑最合适,一觉醒来就同步完了。
提示:可以用
nohup或者screen/tmux把同步任务放到后台,避免 SSH 断开导致任务中断。nohup reposync ... > sync.log 2>&1 &是个常用写法,日志留下来还能事后排查。
5. 下完包还不算完:用 createrepo 生成可用元数据
5.1 为什么光有 rpm 文件不能当源用
很多人第一次做完这一步会懵:明明包都下下来了,为什么配置本地源还是报 "Cannot find a valid baseurl"?原因在于 yum/dnf 通过repodata目录里的元数据文件来索引包,元数据里记录了每个包的名称、版本、依赖、校验值。你只把.rpm文件拷过来,没有元数据,包管理器根本"看不见"这些包。所以下完包后,生成元数据是必须的一步。
即使前面用了--download-metadata带下了原始元数据,我也建议重新生成一次。因为如果你用了-n只下最新版,或者中途手动删过包,原始元数据里记的包和磁盘上实际存在的包就对不上了,装包时会报 "包在元数据里存在但文件找不到"。重新生成元数据能让索引和实际文件严格一致。
5.2 createrepo 命令与生成结果验证
对每个仓库目录单独执行:
createrepo -v /data/kylin-repo/ks10-adv-os/ createrepo -v /data/kylin-repo/ks10-adv-updates/-v是 verbose,输出详细信息,能看到它扫描了多少个包。执行完之后检查目录:
ls /data/kylin-repo/ks10-adv-os/repodata/里面应该会出现repomd.xml、primary.xml.gz、filelists.xml.gz等文件。其中repomd.xml是入口文件,本地源配置正确的话,包管理器第一个找的就是它。
生成过程中如果报了包校验相关的 warning,比如某个包缺少某些标签,通常不影响使用,但如果有 error 就要留意,可能是那个 rpm 文件损坏了,需要删掉重下。
5.3 用 --update 做增量刷新
第一次全量生成后,以后每次往目录里加新包,不需要重新全量生成,用--update只更新变化的部分就行:
createrepo --update -v /data/kylin-repo/ks10-adv-os/这个在增量维护场景里很有用。比如你定期往本地源里补几个新包,用--update几秒钟就刷新完了,比全量重建快得多。但要注意,--update只处理新增和变更的包,如果你删除了包,得用--update配合其他处理或干脆全量重建,否则元数据里还留着被删包的记录。这也是为什么我更推荐"每次同步完就重建元数据"的简单策略,图的就是省心。
6. 把本地目录变成真正可用的源:配置与强制校验
6.1 新建本地 repo 文件的完整内容
在/etc/yum.repos.d/下新建一个kylin-local.repo,内容如下:
[kylin-local-os] name=Kylin Local OS baseurl=file:///data/kylin-repo/ks10-adv-os/ enabled=1 gpgcheck=0 [kylin-local-updates] name=Kylin Local Updates baseurl=file:///data/kylin-repo/ks10-adv-updates/ enabled=1 gpgcheck=0几个关键点:baseurl用的是file://协议加绝对路径,指向的就是包含repodata的那一层目录,路径末尾的斜杠别漏。gpgcheck=0是关掉签名校验,因为本地源里的包签名不一定齐全,临时关掉省事;如果安全要求高,可以gpgcheck=1并配置好gpgkey,但前提是你有正确的公钥。
注意:本地源用
file://协议时,一定要确认路径拼写完全正确,多一层少一层都会导致 "Cannot find a valid baseurl" 报错。用ls命令一层层核对过去最保险。
6.2 禁用外网源,避免混用踩坑
配置本地源的目的是离线使用,如果外网源还开着,机器在联网时会优先走外网源,或者两个源的包版本打架。所以稳妥做法是把外网源禁用掉:
yum-config-manager --disable ks10-adv-os ks10-adv-updates或者直接在原来的 repo 文件里把enabled=1改成enabled=0。也可以临时用参数控制:
yum --disablerepo="*" --enablerepo="kylin-local-*" install <包名>但每次都加这么一长串参数太麻烦,长期用还是改配置文件干净。我个人偏好在离线环境里把所有外网源都设成 disabled,只留本地源,这样机器一旦接入任何网络也不会意外从外网拉包。
6.3 yum clean all 加 makecache 验证
改完配置后,必须清缓存再加缓存,否则 yum 用的还是旧缓存:
yum clean all yum makecache yum repolistyum makecache成功且不报错,yum repolist里能看到你新配的本地源并且有包数量,就算搭好了。如果makecache报错,多半是 baseurl 路径问题或者元数据没生成好,回头检查repodata目录是否存在、repomd.xml是否正常。
6.4 拔网线测试:证明本地源真能用
最后一步是我强烈建议做的——把网卡断开,模拟真实离线环境,然后装一个之前没装过的包:
yum install -y sl如果这个命令能成功从kylin-local-*源装包,说明整套链路没问题。如果报错,说明你还有残留的外网依赖,可能是某些包依赖的库只在旧的外网源里,需要把对应仓库也同步到本地。这一步能提前暴露问题,别等到真进内网了才发现装不上。
7. 踩坑实录:几个让我重新同步一整晚的问题
7.1 磁盘 inode 耗尽导致下载中断
这个问题特别隐蔽。一个源里有成千上万个 rpm 小文件,有时磁盘容量还剩不少,但 inode 已经用光了,表现出来就是突然写不进文件、下载中断、甚至已经下好的文件也出问题。排查用:
df -i /data如果IUse%接近 100%,就是 inode 问题。解决办法是换一个 inode 数量更充足的文件系统,或者在创建时用更大的 inode 比例。这个坑我踩过一次,下了一整晚的包,第二天早上一半文件是空的,重装文件系统才解决。
7.2 源地址中间件限速与超时
有些企业内网会在出网口做流量控制,或者源服务器本身有单连接限速。表现是 reposync 跑得极慢,或者频繁超时断开。遇到这种情况,一是可以调大超时时间,二是问清楚网络策略,看有没有更合适的镜像源。有一回我从官方源拉,速度只有几十 KB 每秒,换成离得近的镜像站后速度翻了几十倍。
7.3 元数据和 rpm 不匹配的诡异报错
现象是包明明在目录里,yum install却说找不到,或者报包损坏。根因通常是:元数据是先前的状态,而目录里的 rpm 后来被手动增删过。解决就是重新createrepo,让元数据和实际文件对齐。这也是我强调"下完包一定重新生成元数据"的原因。
7.4 --norepopath 用错了导致目录嵌套
--norepopath这个参数控制是否把仓库名作为子目录。默认不加时,reposync 会建/data/kylin-repo/ks10-adv-os/;加了之后,包会直接下到/data/kylin-repo/里面,不带仓库名。如果你同时同步多个仓库又加了这个参数,不同仓库的包会混在同一个目录里,元数据也会互相覆盖,最后整个目录一团糟。所以多仓库场景千万别用--norepopath,让它老老实实按仓库名分开目录。
| 报错/现象 | 可能根因 | 处理方式 |
|---|---|---|
| Cannot find a valid baseurl | baseurl 路径错或 repodata 缺失 | 逐层核对路径,重新 createrepo |
| 磁盘写满但容量显示还有空间 | inode 耗尽 | df -i检查,换文件系统 |
| 包存在却提示找不到 | 元数据与文件不一致 | 重新生成元数据 |
| 下载极慢或中断 | 源限速/网络抖动 | 换镜像源,加后台重试 |
| 多仓库包混在一起 | 误用 --norepopath | 去掉该参数,按仓库分目录 |
8. 打包分发与增量维护:把本地源变成长期资产
8.1 打包带走并保留权限
本地源做好之后,如果是要交给内网机器使用,通常需要打包。用 tar 打包时记得保留权限和属主信息:
cd /data tar -cvpf kylin-repo.tar kylin-repo/-p保留权限,-v显示进度,-f指定输出文件。几十 GB 的包打 tar 很慢,可以考虑分卷或者只打包必要仓库。带到内网机器后解压到相同路径:
tar -xvpf kylin-repo.tar -C /data/解压后本地源文件里的 baseurl 路径要和实际解压路径一致,否则又要改配置。所以我在做源的时候就固定用/data/kylin-repo/这个路径,到处解压都不变。
8.2 定期增量同步的脚本化思路
本地源不是一劳永逸的,官方源会更新,你也需要定期同步新包。把这套流程脚本化,每月跑一次:
#!/bin/bash set -e REPOS="ks10-adv-os ks10-adv-updates" ROOT=/data/kylin-repo for r in $REPOS; do reposync -r $r -p $ROOT/ -n --download-metadata createrepo --update -v $ROOT/$r/ done yum clean all yum makecacheset -e保证任何一步出错就停止,避免带着错误继续。因为用了-n和--update,增量同步只处理新包,速度快,适合定期跑。日志重定向到文件方便事后看:
./sync-repo.sh > /var/log/repo-sync-$(date +%F).log 2>&18.3 系统升级后源的迁移注意事项
如果内网机器的麒麟从 SP1 升级到 SP3,原来的本地源不一定还能用,因为系统期望的包版本变了。这时候要重新在能连外网的对应版本机器上同步 SP3 的源,替换掉旧的。迁移时注意几点:一是仓库 ID 可能变了,本地 repo 文件的 baseurl 要跟着改;二是旧源的元数据要清理,别和新源混着;三是升级前最好做一次快照或备份,万一出问题能回退。
我个人的习惯是给每个 SP 版本建独立的目录,比如/data/kylin-repo/sp3/,不同版本互不干扰,升级时只切换本地 repo 文件指向即可,旧源留着还能给还没升级的机器用。这样管理起来清爽,也不会因为一次误操作把整套源搞坏。
8.4 顺手留个校验习惯
最后分享一个我形成习惯的小动作:每次同步完,除了yum makecache,我还会随手装一个平时不太用的小包(比如前面提到的sl)验证一下。这个动作花不了几秒钟,但能在源出问题的第一时间就发现,比等到生产环境要装关键组件时才发现本地源是坏的,代价小得多。
yum --disablerepo="*" --enablerepo="kylin-local-*" install -y sl能装上就说明本地源健康。这套流程我从最早的 CentOS 本地源一路用到麒麟 V10,核心逻辑没变过——把远程源完整搬到本地、生成元数据、配好 file 协议、断开外网验证。真正花时间的从来不是命令本身,而是空间预算、网络稳定性和那些看起来不起眼的路径细节。把这几条牢牢记住,下次再遇到"Kylin v10 整源同步到本地"这种活儿,你基本可以闭着眼睛干完。