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发行版使用不同的包管理器:
image

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发行版中自如地管理软件,无论是搭建生产环境还是开发调试,都能游刃有余。

最后提醒一句:在生产环境中,尽量使用官方仓库或可信第三方的预编译包,避免不必要的源码编译;若必须编译,请做好安装后的配置记录,以便后续维护和卸载。

posted @ 2026-08-31 09:37  GuiGui321  阅读(15)  评论(0)    收藏  举报