适用场景 :麒麟 V10(RPM 系)服务器,无法直接访问互联网,需通过可上网的开发机下载依赖包,离线完成 Python 3.11 源码编译。
关键词:麒麟 V10、Python 3.11、离线安装、RPM 依赖、版本冲突、yum 源
1. 问题背景
1.1. 概述
某公司内网环境中的麒麟 V10 服务器(Advanced Server V10 Halberd,x86_64)需要部署 Python 3.11,但官方软件源中缺少编译所需的开发包(-devel)。我们有一台可上网的开发服务器(同样麒麟 V10),计划从它下载 RPM 包,再导入离线服务器安装。
目标 :编译 Python 3.11.15,并启用 bz2、sqlite3、lzma、_ctypes(依赖 libffi)等标准模块。
1.2. 环境信息
1.2.1. 开发服务器(可上网)
- 操作系统:Kylin Linux Advanced Server V10 (Halberd)
- 架构:x86_64
- 包管理器:YUM
- 软件源配置:
/etc/yum.repos.d/kylin_x86_64.repo(内容见下文) - 用途:下载所需 RPM 包
1.2.2. 目标服务器(离线内网)
- 相同操作系统版本(补丁版本可能略有差异,如
p07vsp35) - 无互联网访问,需离线安装
1.3. 问题现象
1.3.1. 安装python3.11
在编译 Python 3.11 过程报错:
bash
/home/scapp/PVSystem/python/Python-3.11.15/Modules/_ctypes/_ctypes.c:118:10: fatal error: ffi.h: No such file or directory
#include <ffi.h>
^~~~~~~
compilation terminated.
问题原因,缺少 libffi 头文件,同时 bzip2、sqlite3、xz 等相关模块也可能因缺少 -devel 包而无法编译。
1.3.2. 离线安装rpm包报错
从已有相同系统的机器上用 yum reinstall --downloadonly 下载了所有相关 RPM(-devel),拷贝到目标服务器后执行:
bash
sudo yum localinstall *.rpm -y
报错如下:
Error:
Problem 1: conflicting requests
- nothing provides bzip2 = 1.0.8-6.ky10 needed by bzip2-devel-1.0.8-6.ky10.x86_64
Problem 2: conflicting requests
- nothing provides libffi = 3.3-11.ky10 needed by libffi-devel-3.3-11.ky10.x86_64
...(类似错误共 7 个)
原因是只下载了devel包,缺少其相关的基础包。
2. 离线包生成与安装过程
2.1. 在开发服务器上配置 YUM 源并下载完整的 RPM 包
2.1.1. 确认开发服务器的软件源配置
编辑 /etc/yum.repos.d/kylin_x86_64.repo,确保启用了正确的仓库(参考如下):
ini
[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 # 通常不需要启用
注意:不同版本麒麟的仓库地址可能不同,请根据实际情况调整。
也可以指定安装软件位置,如下所示:
ini
[ks10-adv-updates]
name = Kylin Linux Advanced Server 10 - Updates
baseurl = file:///data/software/kylin/update
gpgcheck = 0
enabled = 1
2.1.2. 更新缓存并查看可用的包
bash
sudo yum clean all
sudo yum makecache
2.1.3. 下载完整的 RPM 集合(基础库 + -devel)
关键点 :-devel 包严格依赖于基础库的精确版本 ,仅下载 -devel 会导致目标服务器因基础库版本不匹配而安装失败。必须同时下载基础库。
我们需要下载的包包括:bzip2、libffi、sqlite、xz、openssl、zlib(及其对应的 -devel)。
使用 yum reinstall --downloadonly 可以强制下载已安装的包(包括基础库和开发包),命令如下:
bash
# 创建存放 RPM 的目录
mkdir -p ~/python_deps_rpms
cd ~/python_deps_rpms
# 下载所需的基础库及其 -devel 包(包括依赖)
sudo yum reinstall --downloadonly --downloaddir=. \
bzip2 libffi openssl-libs sqlite xz zlib \
bzip2-devel libffi-devel openssl-devel sqlite-devel xz-devel zlib-devel
为什么这样写?
bzip2、libffi等是基础库,openssl-libs是 OpenSSL 运行时库。- 同时指定基础库和
-devel包,yum会下载所有指定的包及其依赖(如openssl、zlib等)。 - 如果某个包已是最新,
reinstall仍会强制下载当前版本的 RPM。
执行后,~/python_deps_rpms 目录下会生成类似以下文件:
bzip2-1.0.8-6.ky10.x86_64.rpm
bzip2-devel-1.0.8-6.ky10.x86_64.rpm
libffi-3.3-11.ky10.x86_64.rpm
libffi-devel-3.3-11.ky10.x86_64.rpm
openssl-libs-1.1.1f-31.p35.ky10.x86_64.rpm
openssl-devel-1.1.1f-31.p35.ky10.x86_64.rpm
sqlite-3.32.3-8.ky10.x86_64.rpm
sqlite-devel-3.32.3-8.ky10.x86_64.rpm
xz-5.2.5-5.ky10.x86_64.rpm
xz-devel-5.2.5-5.ky10.x86_64.rpm
zlib-1.2.11-23.ky10.x86_64.rpm
zlib-devel-1.2.11-23.ky10.x86_64.rpm
验证 :建议用
ls -l查看文件大小,确保每个包都完整下载(通常几 KB 到几 MB)。
2.2. 将 RPM 包传输到离线目标服务器
使用VPN 或 U 盘将整个 python_deps_rpms 目录拷贝到目标服务器的某个目录,例如 /home/scapp/python/rpms。
bash
# 在开发服务器上打包
tar -czf python_deps_rpms.tar.gz -C ~ python_deps_rpms
在目标服务器上解压:
bash
cd /home/scapp/python
tar -xzf python_deps_rpms.tar.gz
cd python_deps_rpms
2.3. 在目标服务器上安装 RPM 包
2.3.1. 首先检查当前系统已安装的版本
bash
rpm -qa | grep -E "^(bzip2|libffi|openssl-libs|sqlite|xz|zlib)-"
2.3.2. 尝试使用 yum localinstall 安装所有 RPM
bash
sudo yum localinstall *.rpm -y
如果一切顺利 ,所有包会成功安装或升级。但实际中常出现版本冲突,例如:
Error:
Problem 1: conflicting requests
- nothing provides bzip2 = 1.0.8-6.ky10 needed by bzip2-devel-1.0.8-6.ky10.x86_64
...
这是因为目标服务器上的基础库版本(如 bzip2-1.0.8-4.ky10)与下载的 -devel 要求的不匹配(1.0.8-6),YUM 拒绝安装。
2.3.3. 解决方法:强制升级所有 RPM(基础库 + -devel)
由于我们已有完整配套的 RPM,直接强制升级即可:
bash
sudo rpm -Uvh --force --nodeps *.rpm
-Uvh:升级或安装(若已存在则升级)--force:强制覆盖,无视版本冲突--nodeps:忽略依赖(因为包是配套的,实际依赖已满足)
风险提醒 :这会升级 openssl-libs、zlib 等核心库,但版本号相近(如 p07 → p35),一般不会影响系统稳定性。若担心,可分步升级 ,仅升级非核心库(bzip2、libffi、sqlite、xz)及其 -devel,保留 openssl 和 zlib 不变:
bash
sudo rpm -Uvh --nodeps bzip2-* libffi-* sqlite-* xz-*
2.3.4. 验证安装
检查已安装的包版本:
bash
rpm -qa | grep -E "^(bzip2|libffi|openssl-libs|sqlite|xz|zlib)-"
确保版本号与下载的 RPM 一致(或至少 -devel 对应的基础库已升级)。
2.4. 编译 Python 3.11
现在,目标服务器上已有全部所需头文件和库文件。
2.4.1. 下载 Python 源码(可提前在开发机下载并拷贝)
bash
wget https://www.python.org/ftp/python/3.11.15/Python-3.11.15.tgz
tar -xzvf Python-3.11.15.tgz
cd Python-3.11.15
2.4.2. 配置编译选项
bash
./configure --prefix=/usr/local/python3.11 --enable-optimizations
2.4.3. 编译并安装
bash
make -j$(nproc)
sudo make altinstall
重要 :务必使用
altinstall,避免覆盖系统自带的python3。
2.5. 验证编译结果
安装完成后,测试所有模块是否可用:
bash
/usr/local/python3.11/bin/python3.11 -c "import bz2, sqlite3, lzma, ctypes; print('All modules imported successfully!')"
若输出成功信息,则所有依赖模块均已正常启用。
3. 问题复盘与经验总结
3.1. 核心问题
- 官方源缺失开发包 :麒麟 V10 默认源不包含
-devel包,需手动补充。 - 版本不一致导致安装失败 :
-devel包依赖基础库的精确版本,若基础库版本较旧,YUM 会拒绝安装。 - 只下载
-devel不解决问题:必须同时下载对应版本的基础库。
3.2. 解决关键
- 在可上网的开发机上,使用
yum reinstall --downloadonly同时下载基础库和-devel。 - 在目标服务器上,采用
rpm -Uvh --force --nodeps强制升级全套 RPM,使版本一致。 - 若担心核心库升级影响服务,可仅升级非核心库(
bzip2、libffi、sqlite、xz)。
3.3. 经验启示
- 离线环境务必版本匹配:开发机和目标机系统版本(包括补丁号)最好一致,否则需强制覆盖。
- 善用
yum reinstall --downloadonly:此命令可下载已安装包的当前版本,适合导出环境。 altinstall保护系统 :始终使用altinstall安装自编译 Python。- 编译前清理 :若之前编译失败,执行
make clean避免残留。
参考资料:
本文档基于实际项目经验整理,已在麒麟 V10(Halberd)环境中验证通过。
如果你也遇到了类似问题,欢迎参考本文的步骤,结合自己的环境调整。如有疑问,可以在评论区留言交流。