本文介绍在内网中搭建某国产Linux系统yum源服务器。
一、背景
某局域网因故不能连接互联网,在Linux中安装缺少的软件较麻烦,为此,抽时间研究了如何在内网搭建Linux源,并进行了实践。同时为后续在内网中安装软件、更新补丁做技术储备。
二、分析
2.1、目标分析
目标系统为kylin服务器版,软件安装方式为yum,分析官方源的地址可知,NS为根目录,下有多个目录,V10下有多个不同发行版本目录,如当前使用的版本为V10SP3-2403
,再直接到os/adv/lic
,下有base和updates,下有不同架构名称。如:
https://update.cs2c.com.cn/NS/V10/V10SP3-2403/os/adv/lic/base/
x86架构的rpm软件包位置如下:
https://update.cs2c.com.cn/NS/V10/V10SP3-2403/os/adv/lic/updates/x86_64/Packages/
2.2、步骤分析
根据搜索到的资料,搭建yum服务主要有几个步骤:
1、需要一台中介服务器,能连互联网。
2、yum支持http、https、ftp方式下载安装。大部分使用http方式,可用httpd、nginx、candy等在中介服务器上搭建http服务器。
3、再同步官方源文件到指定目录,该目录能够在网页上打开。
4、在需要安装软件的机器上,更新yum源仓库地址,即可安装软件。
三、实践
3.1、总体设计
1、经个人评估,目前能预见的时间内,访问量不会很大,为减少部署时间,不借用第三方软件,而是使用golang编写http服务器,可在运行时指定目录,指定端口。
2、经分析,工程/运行目录设计如下:
# tree -L 5
.
├── http_server
├── http_server.go
├── log
├── repos
│ └── x86_64
│ ├── base
│ │ └── ks10-adv-os
│ │ ├── Packages
│ │ └── repodata
│ └── updates
│ └── ks10-adv-updates
│ ├── Packages
│ └── repodata
└── run.sh
11 directories, 5 files
其中,http_server
为http服务器运行程序,repos
为软件源的目录,具体是:
base
类型的安装包文件在repos/x86_64/base/ks10-adv-os/Packages/
目录,数据文件在repos/x86_64/base/ks10-adv-os/Packages/repodata/
。
updates
类型的安装包文件在repos/x86_64/updates/ks10-adv-updates/Packages/
目录,数据文件在repos/x86_64/updates/ks10-adv-updates/repodata/
。
相比于官方源的地址减少了一些目录。如此设计repos
,是因为使用reposync
下载时自动创建了ks10-adv-os
和ks10-adv-updates
目录,因此,在下文中指定仓库地址时,会与官方的不同。
3、笔者使用2台电脑进行实验,一台为中介服务器,IP为192.168.28.28
,端口为87。另一台为本地虚拟机,用来安装软件以验证源服务器是否正常。两者硬件架构、操作系统均相同。
3.2、搭建http服务器
起初,笔者使用了nginx镜像搭建http服务器,后舍弃掉,改为自建服务器,源码见附录。
在测试过程中,由于服务器开了防火墙,因此需要开放相应的端口,示例如下:
sudo firewall-cmd --add-port=9000/tcp --permanent
sudo firewall-cmd --add-port=87/tcp --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --add-masquerade --permanent # docker相关
sudo firewall-cmd --reload
查看开放端口:
sudo firewall-cmd --list-ports
查看防火墙状态:
sudo systemctl status firewalld
3.3、同步远程仓库
一般地,需要在中介服务器上,使用reposync
命令同步
# 同步 BaseOS
nohup dnf reposync --repoid=ks10-adv-os --download-metadata --remote-time --newest-only -p repos/x86_64/base &
# 同步 Updates
nohup dnf reposync --repoid=ks10-adv-updates --download-metadata --remote-time --newest-only -p repos/x86_64/updates/ &
ks10-adv-os 表示yum仓库配置字段名,在/etc/yum.repos.d/kylin_x86_64.repo中可查
--remote-time 表示保持远程仓库文件的修改时间
注:如已下载有,则会跳过。
上述命令执行完毕后,仓库体积大约占用18GB。由于使用后台方式下载,没有计算具体的耗时。笔者网速一般快,大概个把小时即完成。
但是,起初笔者并没有那么多时间等待,于是找了另外的途径。以安装bison
为例,将官方的base
的repodata
下载到中介服务器repos/x86_64/base/ks10-adv-os/Packages/repodata/
目录中,再找到bison-3.6.4-3.ky10.x86_64.rpm
安装文件,放到repos/x86_64/base/ks10-adv-os/Packages/
目录中。官方具体目录为:
通过上述方法,可以较快地验证。当然,还是需要同步完所有的文件才算完整。
要再次说明的是,笔者的中介服务器为x86架构,而虚拟机也是x86架构,两者操作系统相同。中介服务器本身的源没有修改,因此,reposync
能正常同步,至于使用不同架构,限于精力,笔者未进行试验。
3.4、运行服务器
命令:
./http_server --dir ./repos -p 87
在浏览器中访问,效果如下:
下面是更新完所有包的截图:
3.5、仓库配置
服务器准备就绪后,就可以进行验证了,在虚拟机中,查看官方的kylin_x86_64.repo
文件:
# cat /etc/yum.repos.d/kylin_x86_64.repo
###Kylin Linux Advanced Server 10 - os repo###
[ks10-adv-os]
name = Kylin Linux Advanced Server 10 - Os
baseurl = https://update.cs2c.com.cn/NS/V10/V10SP3-2403/os/adv/lic/base/$basearch/
gpgcheck = 1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kylin
enabled = 1
[ks10-adv-updates]
name = Kylin Linux Advanced Server 10 - Updates
baseurl = https://update.cs2c.com.cn/NS/V10/V10SP3-2403/os/adv/lic/updates/$basearch/
gpgcheck = 1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kylin
enabled = 1
[ks10-adv-addons]
name = Kylin Linux Advanced Server 10 - Addons
baseurl = https://update.cs2c.com.cn/NS/V10/V10SP3-2403/os/adv/lic/addons/$basearch/
gpgcheck = 1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kylin
enabled = 0
根据官方示例修改,新建inner_kylin_x86_64.repo
文件:
###Kylin Linux Advanced Server 10 - 内部源服务配置###
[ks10-adv-os-inner]
name = Kylin Linux Advanced Server 10 - Os
#baseurl = http://192.168.28.28:87/V10SP3-2403/os/adv/lic/base/$basearch/
baseurl = http://172.16.9.19:87/x86_64/base/ks10-adv-os/
gpgcheck = 0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kylin
enabled = 1
[ks10-adv-updates-inner]
name = Kylin Linux Advanced Server 10 - Updates
#baseurl = http://192.168.28.28:87/V10SP3-2403/os/adv/lic/updates/$basearch/
baseurl = http://172.16.9.19:87/x86_64/updates/ks10-adv-updates/
gpgcheck = 0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kylin
enabled = 1
主要修改了baseurl
为实际的URL,另外不使能gpgcheck
。经确认,官方文件的ks10-adv-addons
指示的地址没有找到,因此未添加。
备份原来的,拷贝新的:
sudo mv /etc/yum.repos.d/kylin_x86_64.repo /etc/yum.repos.d/backup
sudo cp inner_kylin_x86_64.repo /etc/yum.repos.d/
3.6、更新源仓库
在虚拟机中更新缓存,命令如下:
sudo yum clean all # 清理缓存
sudo yum repolist enabled # 列出可用的仓库列表。
sudo yum makecache # 生成缓存,以便Yum可以使用新的仓库。
下面列出可用仓库列表信息(与上述配置文件一致):
$ sudo yum repolist enabled
repo id repo name
ks10-adv-os-inner Kylin Linux Advanced Server 10 - Os
ks10-adv-updates-inner Kylin Linux Advanced Server 10 - Updates
下面生成缓存信息:
$ sudo yum makecache
Kylin Linux Advanced Server 10 - Os 156 kB/s | 3.7 kB 00:00
Kylin Linux Advanced Server 10 - Updates 3.7 MB/s | 9.8 MB 00:02
Metadata cache created.
3.7、安装软件示例
以安装bison
软件为例,命令如下:
sudo dnf install bison
输出信息如下:
$ sudo dnf install bison
Last metadata expiration check: 0:02:15 ago on 2025年04月02日 星期三 19时13分39秒.
Dependencies resolved.
===================================================================================================
Package Architecture Version Repository Size
===================================================================================================
Installing:
bison x86_64 3.6.4-3.ky10 ks10-adv-os-inner 333 k
Transaction Summary
===================================================================================================
Install 1 Package
Total download size: 333 k
Installed size: 1.1 M
Is this ok [y/N]: y
Downloading Packages:
bison-3.6.4-3.ky10.x86_64.rpm 712 kB/s | 333 kB 00:00
---------------------------------------------------------------------------------------------------
Total 704 kB/s | 333 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : bison-3.6.4-3.ky10.x86_64 1/1
Verifying : bison-3.6.4-3.ky10.x86_64 1/1
Installed:
bison-3.6.4-3.ky10.x86_64
Complete!
使用自建http服务,日志输出示例:
[INFO] 2025/04/02 19:15:57 10.20.5.103 | GET /x86_64/base/ks10-adv-os/Packages/bison-3.6.4-3.ky10.x86_64.rpm | 11.020931ms
查看版本号:
$ bison --version
bison (GNU Bison) 3.6.4
Written by Robert Corbett and Richard Stallman.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
输出结果与上文的版本一致,至此,完成了验证,实现了闭环。
四、小结
目前只是在测试阶段。还没有正式使用,根据网上说法,可以用crontab
脚本定期更新。不过,在笔者的环境中,需要将外部网络服务器的仓库文件,手动拷贝到内部网络的服务器上,鉴于其体积有18GB------即使压缩了,体积也有17GB,再考虑到网速问题,工作耗时还是不少的。另外,目前也没有细究如何做增量同步。
而其它如arm架构,桌面版本源,等,只能择机再做了。自去年年底有心想做,到现在3个多月了,有个阶段性结果,也是个交待了。
附:http服务器http_server.go源码
/*
本工程全部代码由AI工具经过多轮迭代生成
*/
package main
import (
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"time"
)
var (
dir = flag.String("dir", ".", "Directory to serve")
port = flag.String("p", "8000", "Port to listen on")
)
// 自定义日志记录器
var (
infoLogger *log.Logger
errorLogger *log.Logger
)
func initLoggers() error {
// 创建 log 目录(如果不存在)
if err := os.MkdirAll("log", 0755); err != nil {
return fmt.Errorf("failed to create log directory: %v", err)
}
// 按日期命名日志文件(如 ./log/2023-10-01.log)
logFileName := filepath.Join("log", time.Now().Format("2006-01-02")+".log")
logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("failed to open log file: %v", err)
}
// 同时输出到文件和控制台
multiWriter := io.MultiWriter(os.Stdout, logFile)
infoLogger = log.New(multiWriter, "[INFO] ", log.LstdFlags)
errorLogger = log.New(multiWriter, "[ERROR] ", log.LstdFlags)
return nil
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
// 记录:IP | 方法 | 路径 | 耗时
infoLogger.Printf("%s | %s %s | %v",
getClientIP(r),
r.Method,
r.URL.Path,
time.Since(start),
)
})
}
func getClientIP(r *http.Request) string {
// 获取真实 IP(处理代理情况)
ip := r.Header.Get("X-Forwarded-For")
if ip == "" {
ip = r.Header.Get("X-Real-IP")
}
if ip == "" {
ip = r.RemoteAddr
}
return ip
}
func main() {
flag.Parse()
// 初始化日志系统
if err := initLoggers(); err != nil {
log.Fatalf("Init failed: %v", err)
}
// 检查目录是否存在
if _, err := os.Stat(*dir); os.IsNotExist(err) {
errorLogger.Fatalf("Directory %s does not exist", *dir)
}
// 标准化目录路径
absDir, err := filepath.Abs(*dir)
if err != nil {
errorLogger.Fatalf("Failed to get absolute path: %v", err)
}
// 文件服务器 + 日志中间件
fs := loggingMiddleware(http.FileServer(http.Dir(absDir)))
// 启动服务器
addr := fmt.Sprintf(":%s", *port)
infoLogger.Printf("Serving directory %s on http://0.0.0.0:%s", absDir, *port)
errorLogger.Fatal(http.ListenAndServe(addr, fs))
}
附:其它
下载示例
[toll@192 yum_nginx]$ flex
-bash: flex:未找到命令
[toll@192 yum_nginx]$ sudo yum install flex
Last metadata expiration check: 0:01:13 ago on 2025年04月01日 星期二 19时30分21秒.
Dependencies resolved.
===================================================================================================
Package Architecture Version Repository Size
===================================================================================================
Installing:
flex x86_64 2.6.4-5.ky10 ks10-adv-os 305 k
Transaction Summary
===================================================================================================
Install 1 Package
Total download size: 305 k
Installed size: 909 k
Is this ok [y/N]: y
Downloading Packages:
[MIRROR] flex-2.6.4-5.ky10.x86_64.rpm: Status code: 404 for http://192.168.28.28:87/V10SP3-2403/os/adv/lic/base/x86_64/Packages/flex-2.6.4-5.ky10.x86_64.rpm (IP: 192.168.28.24)
[MIRROR] flex-2.6.4-5.ky10.x86_64.rpm: Status code: 404 for http://192.168.28.28:87/V10SP3-2403/os/adv/lic/base/x86_64/Packages/flex-2.6.4-5.ky10.x86_64.rpm (IP: 192.168.28.24)
[MIRROR] flex-2.6.4-5.ky10.x86_64.rpm: Status code: 404 for http://192.168.28.28:87/V10SP3-2403/os/adv/lic/base/x86_64/Packages/flex-2.6.4-5.ky10.x86_64.rpm (IP: 192.168.28.24)
[MIRROR] flex-2.6.4-5.ky10.x86_64.rpm: Status code: 404 for http://192.168.28.28:87/V10SP3-2403/os/adv/lic/base/x86_64/Packages/flex-2.6.4-5.ky10.x86_64.rpm (IP: 192.168.28.24)
[FAILED] flex-2.6.4-5.ky10.x86_64.rpm: No more mirrors to try - All mirrors were already tried without success
The downloaded packages were saved in cache until the next successful transaction.
You can remove cached packages by executing 'yum clean packages'.
Error: Error downloading packages:
flex-2.6.4-5.ky10.x86_64: Cannot download, all mirrors were already tried without success
[toll@192 yum_nginx]$ sudo yum install flex
Kylin Linux Advanced Server 10 - Os 1.2 MB/s | 3.7 kB 00:00
Dependencies resolved.
===================================================================================================
Package Architecture Version Repository Size
===================================================================================================
Installing:
flex x86_64 2.6.4-5.ky10 ks10-adv-os 305 k
Transaction Summary
===================================================================================================
Install 1 Package
Total download size: 305 k
Installed size: 909 k
Is this ok [y/N]: y
Downloading Packages:
flex-2.6.4-5.ky10.x86_64.rpm 38 MB/s | 305 kB 00:00
---------------------------------------------------------------------------------------------------
Total 30 MB/s | 305 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : flex-2.6.4-5.ky10.x86_64 1/1
Running scriptlet: flex-2.6.4-5.ky10.x86_64 1/1
Verifying : flex-2.6.4-5.ky10.x86_64 1/1
Installed:
flex-2.6.4-5.ky10.x86_64
Complete!
[toll@192 yum_nginx]$
卸载flex同时卸载其它依赖库示例
sudo yum remove flex
Dependencies resolved.
===================================================================================================
Package Architecture Version Repository Size
===================================================================================================
Removing:
flex x86_64 2.6.4-5.ky10 @anaconda 909 k
Removing dependent packages:
kpatch x86_64 1:0.9.1-20.p01.ky10 @anaconda 312 k
Removing unused dependencies:
bison x86_64 3.6.4-3.ky10 @anaconda 1.1 M
e2fsprogs-devel x86_64 1.45.6-20.ky10 @anaconda 1.0 M
keyutils-libs-devel x86_64 1.6.3-4.ky10 @anaconda 12 k
krb5-devel x86_64 1.18.2-8.ky10 @anaconda 824 k
libverto-devel x86_64 0.3.1-6.ky10 @anaconda 31 k
openssl-devel x86_64 1:1.1.1f-31.p23.ky10 @anaconda 7.9 M
Transaction Summary
===================================================================================================
Remove 8 Packages
Freed space: 12 M
Is this ok [y/N]: y
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Running scriptlet: kpatch-1:0.9.1-20.p01.ky10.x86_64 1/1
Erasing : kpatch-1:0.9.1-20.p01.ky10.x86_64 1/8
Running scriptlet: kpatch-1:0.9.1-20.p01.ky10.x86_64 1/8
Erasing : openssl-devel-1:1.1.1f-31.p23.ky10.x86_64 2/8
Erasing : krb5-devel-1.18.2-8.ky10.x86_64 3/8
Running scriptlet: e2fsprogs-devel-1.45.6-20.ky10.x86_64 4/8
Erasing : e2fsprogs-devel-1.45.6-20.ky10.x86_64 4/8
Erasing : keyutils-libs-devel-1.6.3-4.ky10.x86_64 5/8
Erasing : libverto-devel-0.3.1-6.ky10.x86_64 6/8
Erasing : bison-3.6.4-3.ky10.x86_64 7/8
Running scriptlet: flex-2.6.4-5.ky10.x86_64 8/8
Erasing : flex-2.6.4-5.ky10.x86_64 8/8
Running scriptlet: flex-2.6.4-5.ky10.x86_64 8/8
Verifying : bison-3.6.4-3.ky10.x86_64 1/8
Verifying : e2fsprogs-devel-1.45.6-20.ky10.x86_64 2/8
Verifying : flex-2.6.4-5.ky10.x86_64 3/8
Verifying : keyutils-libs-devel-1.6.3-4.ky10.x86_64 4/8
Verifying : kpatch-1:0.9.1-20.p01.ky10.x86_64 5/8
Verifying : krb5-devel-1.18.2-8.ky10.x86_64 6/8
Verifying : libverto-devel-0.3.1-6.ky10.x86_64 7/8
Verifying : openssl-devel-1:1.1.1f-31.p23.ky10.x86_64 8/8
Removed:
bison-3.6.4-3.ky10.x86_64 e2fsprogs-devel-1.45.6-20.ky10.x86_64
flex-2.6.4-5.ky10.x86_64 keyutils-libs-devel-1.6.3-4.ky10.x86_64
kpatch-1:0.9.1-20.p01.ky10.x86_64 krb5-devel-1.18.2-8.ky10.x86_64
libverto-devel-0.3.1-6.ky10.x86_64 openssl-devel-1:1.1.1f-31.p23.ky10.x86_64
Complete!
[toll@192 yum_nginx]$ sudo yum install flex
Last metadata expiration check: 0:37:41 ago on 2025年04月01日 星期二 17时59分10秒.
Dependencies resolved.
===================================================================================================
Package Architecture Version Repository Size
===================================================================================================
Installing:
flex x86_64 2.6.4-5.ky10 ks10-adv-os 305 k
Transaction Summary
===================================================================================================
Install 1 Package
Total download size: 305 k
Installed size: 909 k
Is this ok [y/N]: y
Downloading Packages:
flex-2.6.4-5.ky10.x86_64.rpm 1.8 MB/s | 305 kB 00:00
---------------------------------------------------------------------------------------------------
Total 1.8 MB/s | 305 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : flex-2.6.4-5.ky10.x86_64 1/1
Running scriptlet: flex-2.6.4-5.ky10.x86_64 1/1
Verifying : flex-2.6.4-5.ky10.x86_64 1/1
Installed:
flex-2.6.4-5.ky10.x86_64
Complete!
保持远程文件修改时间
# ls repos/x86_64/base/ks10-adv-os/Packages/bison-* -lh
-rw-r--r-- 1 root root 334K 4月 26 2024 repos/x86_64/base/ks10-adv-os/Packages/bison-3.6.4-3.ky10.x86_64.rpm
-rw-r--r-- 1 root root 35K 4月 26 2024 repos/x86_64/base/ks10-adv-os/Packages/bison-devel-3.6.4-3.ky10.x86_64.rpm
-rw-r--r-- 1 root root 245K 4月 26 2024 repos/x86_64/base/ks10-adv-os/Packages/bison-help-3.6.4-3.ky10.noarch.rpm
-rw-r--r-- 1 root root 144K 4月 26 2024 repos/x86_64/base/ks10-adv-os/Packages/bison-lang-3.6.4-3.ky10.x86_64.rpm
可以看到,是2024年4月底更新的。