Linux程序包管理详解:从rpm到dnf再到源码编译
在Linux系统中,程序包管理是运维和开发人员必须掌握的核心技能之一。无论是安装一个Web服务器、部署一套容器编排工具,还是自己编译一个定制化的软件,都离不开对程序包管理机制的理解。本文将从基础概念出发,逐步深入讲解rpm、yum/dnf以及源码编译安装的全流程。
一、基础概念:程序包是什么?
1.1 API与ABI
- API(Application Program Interface):源代码层面的接口,例如函数声明、头文件定义。
- ABI(Application Binary Interface):二进制层面的接口,决定可执行文件能否在不同环境中运行。Unix-like系统通常使用ELF格式,Windows使用PE(exe/msi)。
库级别的虚拟化技术可以跨平台运行二进制程序,例如Linux下的Wine(运行Windows程序)、Windows下的Cygwin(模拟POSIX环境)。
1.2 程序的类型
- 系统级开发(C/C++):如httpd、vsftpd、nginx,编译为机器码直接运行。
- 基础设施服务(Go):如docker、k8s、etcd,静态编译,分发方便。
- 应用级开发(Java/Python/PHP等):需要运行时虚拟机(JVM、PVM等),程序格式为字节码或解释型脚本。
1.3 程序包的构成
一个典型的二进制程序包包含:
- 二进制程序(可执行文件)
- 库文件(共享对象.so)
- 配置文件(如/etc/下的文件)
- 帮助文档(man手册、README等)
1.4 依赖关系
软件包之间往往存在依赖链。例如包A依赖B和C,而B又依赖D。程序包管理器必须能自动处理这些依赖,否则手动安装将极其痛苦。
二、程序包管理器概览
不同的Linux发行版使用不同的包管理器:

2.1 RPM包命名规则
name-VERSION-release.arch.rpm
- VERSION:主版本号.次版本号.修订号(如3.0.21)
- release:rpm包的发行号,常包含操作系统版本(如1.centos7.x86_64)
- arch:架构,如x86_64、i386、noarch(不依赖架构)
2.2 拆包(Subpackage)
大型软件常被拆分为主包和多个支包:
name:主包,包含基本功能name-devel:开发头文件和静态库name-libs:运行时库name-utils:附加工具
三、rpm命令详解
rpm是Red Hat系列最底层的包管理工具,直接操作.rpm文件。虽然日常更多使用yum/dnf,但理解rpm有助于排查问题和编写自动化脚本。
3.1 安装
rpm -ivh package.rpm
-i:安装-v:显示详细信息-h:显示进度条(每个#代表2%)
常用选项:
--test:仅测试,不实际安装--nodeps:忽略依赖(危险,可能导致系统不稳定)--replacepkgs:覆盖安装(不执行卸载脚本,仅替换文件)--noscripts:不执行安装脚本(pre/post脚本)
3.2 升级与降级
rpm -Uvh package.rpm # 升级或安装(若不存在则安装)
rpm -Fvh package.rpm # 仅升级(若不存在则忽略)
--oldpackage:允许降级--force:强制升级(忽略依赖)
⚠️ 注意:内核不要用-U升级,应直接安装新版本(-ivh),因为Linux支持多内核共存。
3.3 卸载
rpm -e package_name
--allmatches:卸载所有匹配版本--nodeps:忽略依赖--test:测试卸载
3.4 查询(最重要)
rpm -q package_name # 查询是否安装及版本
rpm -qa # 列出所有已安装包
rpm -qf /path/to/file # 查询文件属于哪个包
rpm -ql package_name # 列出包安装的所有文件
rpm -qi package_name # 显示包信息
rpm -qc package_name # 列出配置文件
rpm -qd package_name # 列出文档
rpm -q --provides package # 查看包提供的能力
rpm -qR package # 查看包的依赖
rpm -qp --scripts pkg.rpm # 查看未安装包的脚本
3.5 校验
rpm -V package_name
输出中每个字符的含义:
S:文件大小改变M:权限或类型改变5:MD5校验和不符D:设备号不匹配L:符号链接路径变化U:属主改变G:属组改变T:修改时间改变P:能力集改变
3.6 数据库维护
rpm的数据库位于/var/lib/rpm/(CentOS 7以前为BerkeleyDB,EL8+为SQLite3)。
rpm --initdb # 初始化数据库(若不存在则创建)
rpm --rebuilddb # 重建数据库(读取已安装包重新生成)
3.7 包签名验证
导入公钥后,安装时会自动验证来源和完整性:
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-ANOLIS
rpm -K package.rpm # 手动验证
四、yum/dnf:前端包管理工具
4.1 仓库(Repository)配置
仓库配置文件位于/etc/yum.repos.d/(或/etc/dnf/dnf.conf + /etc/dnf/repos.d/),格式如下:
[repositoryID]
name=仓库描述
baseurl=http://mirror.example.com/centos/$releasever/os/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EXAMPLE
常用变量:
$releasever:OS主版本号(如8)$basearch:基础架构(如x86_64)$arch:具体架构(如x86_64)
4.2 dnf常用命令(CentOS 8+/Fedora)
dnf repolist # 列出仓库
dnf list installed # 列出已安装包
dnf list available # 列出可用包
dnf install package # 安装
dnf reinstall package # 重新安装
dnf update # 升级所有包
dnf update package # 升级指定包
dnf downgrade package # 降级
dnf remove package # 卸载
dnf info package # 查看包信息
dnf provides /path/to/file # 查找文件属于哪个包
dnf search keyword # 搜索包名和摘要
dnf clean all # 清理缓存
dnf makecache # 构建缓存
dnf history # 查看事务历史
包组管理
dnf group list
dnf group info "Development Tools"
dnf group install "Development Tools"
4.3 使用本地光盘作为仓库
mount -r /dev/cdrom /media/cdrom
cat > /etc/yum.repos.d/local.repo <<EOF
[LocalRepo]
name=Local CDROM
baseurl=file:///media/cdrom
enabled=1
gpgcheck=0
EOF
4.4 创建自己的仓库
使用createrepo_c命令:
createrepo_c /path/to/rpm/directory
生成repodata目录后,即可配置baseurl指向该目录。
五、源码编译安装
当官方没有提供现成的二进制包,或者需要自定义编译参数时,就需要从源代码编译。
5.1 典型的三步曲
./configure
make
make install
第一步:configure
configure脚本负责:
- 检查编译环境(编译器、头文件、库)
- 根据用户选项生成Makefile
常用选项:
./configure --prefix=/usr/local/appname \
--sysconfdir=/etc/appname \
--enable-feature \
--with-package=/path
--prefix:安装路径(默认/usr/local)--sysconfdir:配置文件目录--enable-FEATURE:启用某个特性--with-PACKAGE:指定依赖包路径--disable-FEATURE:禁用特性--without-PACKAGE:不使用某个包
第二步:make
调用make命令读取Makefile,编译源代码生成目标文件。
第三步:make install
将编译好的程序、库、配置文件等复制到指定目录。
5.2 安装后的配置
1. 导出二进制到PATH
创建/etc/profile.d/appname.sh:
export PATH=/usr/local/appname/bin:$PATH
重新登录或source生效。
2. 导出库文件
创建/etc/ld.so.conf.d/appname.conf,写入库目录路径:
/usr/local/appname/lib
然后运行ldconfig更新缓存。
3. 导出头文件
建立软链接到系统头文件目录:
ln -sv /usr/local/appname/include /usr/include/appname
这样在代码中可以用#include <appname/header.h>。
4. 导出帮助手册
方法一:编辑/etc/man_db.conf,添加MANPATH行。
方法二:在profile脚本中设置:
export MANPATH=/usr/local/appname/share/man:$MANPATH
然后执行mandb更新索引。
5.3 卸载源码编译的软件
由于没有注册到rpm数据库,只能手动清理:
rm -rf /usr/local/appname
rm -f /etc/ld.so.conf.d/appname.conf
rm -f /etc/profile.d/appname.sh
rm -f /usr/include/appname
ldconfig
mandb
如果源码目录还在,可进入后执行make uninstall(部分项目支持)。
六、总结
Linux程序包管理是一个层次分明的体系:
- 底层:rpm/dpkg直接操作包文件,适合查询、校验和紧急修复。
- 中层:yum/dnf/apt自动解决依赖,是日常管理的主力。
- 上层:源码编译提供最大灵活性,适用于定制化场景。
掌握这三层工具,你就能在任何Linux发行版中自如地管理软件,无论是搭建生产环境还是开发调试,都能游刃有余。
最后提醒一句:在生产环境中,尽量使用官方仓库或可信第三方的预编译包,避免不必要的源码编译;若必须编译,请做好安装后的配置记录,以便后续维护和卸载。

浙公网安备 33010602011771号