Linux 软件包管理

本文合并自:04-软件管理-RPM-YUM-源码包.md、06-软件包管理.md、1-5-Linux软件包管理.md、05-进程管理与压缩归档.md(压缩与归档部分)

适用环境:RHEL/CentOS 6 与 RHEL/CentOS 7 并列讲解,涉及版本差异处均单独标注;部分内容同时给出 CentOS 8+ / RHEL 8+ 的 dnf 写法。

内容覆盖:软件包种类与命名规则、压缩与归档(gzip/bzip2/xz/zip/compress/tar/split)、RPM 包管理、src.rpm 重编译、YUM 仓库配置与使用、源码包编译安装、GPG 签名与加密、常见排错与练习。

说明:源文档 05-进程管理与压缩归档.md 中的进程管理部分(ps、kill)不属于本章范围。 详见 阶段04 进程与任务管理


本章要点

  • 了解 Linux 常见软件安装方式:rpm、yum/dnf、deb/apt-get、源码编译,以及源码包与二进制包的区别。
  • 掌握压缩与归档:gzip/gunzip、bzip2/bunzip2、xz/unxz、zip/unzip、compress、rar 的用法与压缩率/速度取舍。
  • 掌握 tar 的打包、解包、查看、更新、追加、对比、删除、排除、权限保留等完整参数,以及配合 gzip/bzip2/xz 的压缩解压和「万能解压」。
  • 掌握 split 分割大文件与常用备份归档组合命令。
  • 掌握 rpm 包命名规则、安装/升级/卸载/查询/校验命令及常用安装选项,理解 --nodeps、--force 的风险。
  • 掌握 yum 的工作原理与元数据结构,会配置本地光盘源、网络源、镜像源,会用 createrepo 自建仓库、用 priorities 插件控制优先级。
  • 掌握 yum 常用子命令:install/remove/update/list/info/search/provides/groupinstall/grouplist/history/clean all/makecache/deplist。
  • 掌握源码包编译安装「解压 → configure → make → make install」的完整流程、常用 configure 参数、卸载方法,以及纳入 PATH 与 systemd 管理的做法。
  • 掌握源码编译常见问题(找不到 .h、找不到库、undefined reference、运行时找不到 .so)的排查思路与 gcc 参数 -I/-L/-l/LD_LIBRARY_PATH/ldconfig。
  • 掌握 GPG 非对称加密:创建密钥对、加密/解密、公钥/私钥导入导出、密钥信任。

一、软件包管理概述

1.1 Linux 常见的软件安装方式

Linux 上常见的软件安装方式有:rpm、yum、deb/apt-get、编译源码。

  • rpm:RedHat Package Manager,RedHat 系(RHEL/CentOS/Fedora)使用的特定压缩包格式与其管理命令。
  • yum:Yellowdog Updater Modified,在 rpm 之上封装,自动处理 rpm 包间依赖,底层仍然调用 rpm。CentOS 8 / RHEL 8 起被 dnf 取代(yum 保留为 dnf 的软链接)。
  • deb / apt-get:Debian / Ubuntu 系包管理。
  • 源码编译:下载源码压缩包,自行 configure、make、make install。

1.2 软件包种类

类型 后缀 说明
RPM 包 .rpm Red Hat 系(RHEL/CentOS/Fedora)使用的二进制包格式
DEB 包 .deb Debian/Ubuntu 系使用的二进制包格式
源码 RPM .src.rpm 包含源码和 spec 宏文件,需编译生成 RPM
源码包 .tar.gz / .tgz / .tar.bz2 / .tar.xz 原始源代码压缩包,需自行编译安装

软件包的演进关系:

源码包  →  .src.rpm  →  .rpm

1.3 源码包与二进制包的区别

类型 优点 缺点
RPM 包(二进制包) 安装快、方便、易管理,有统一的数据库可查询/校验/卸载 功能固定,不能灵活定制;编译参数由打包者决定
源码包 功能可自定义、可裁剪、可打补丁、可指定安装路径与优化选项 安装步骤多、编译耗时长、依赖需手动解决、对技术要求高、卸载不便
  • 二进制包是打包者在特定平台上已经编译完成的成品,安装 rpm 包本质上就是解压压缩包,把已编译好的文件按一定规则释放到系统中;rpm 命令即用于解析这种压缩包。
  • 源码包是未编译的源代码,必须在本机编译成二进制才能运行,因此可以针对本机 CPU、依赖库版本、所需功能做定制。
  • 源码发布平台常用:http://www.sourceforge.net、GitHub 等。查找 rpm 包可访问:http://rpmfind.net。

1.4 各发行版包管理体系对比

发行版系列 包格式 底层工具 前端(自动解依赖)工具 仓库元数据
RHEL / CentOS 6 .rpm rpm yum repodata/repomd.xml
RHEL / CentOS 7 .rpm rpm yum(可选装 dnf) repodata/repomd.xml
RHEL / CentOS 8+、Fedora .rpm rpm dnf(yum 为其软链接) repodata/repomd.xml
SUSE / openSUSE .rpm rpm zypper repodata/
Debian / Ubuntu .deb dpkg apt-get / apt Packages.gz / Release
Arch Linux .pkg.tar.zst — pacman db.tar.gz
Alpine .apk — apk APKINDEX.tar.gz

常见命令对应关系:

操作 RHEL 6(yum) RHEL 8+(dnf) Debian/Ubuntu
安装 yum install pkg dnf install pkg apt-get install pkg
卸载 yum remove pkg dnf remove pkg apt-get remove pkg
升级全部 yum update dnf upgrade apt-get upgrade
搜索 yum search 关键字 dnf search 关键字 apt-cache search 关键字
查询文件归属 rpm -qf 文件 rpm -qf 文件 dpkg -S 文件
列出包内文件 rpm -ql 包名 rpm -ql 包名 dpkg -L 包名
清缓存 yum clean all dnf clean all apt-get clean

1.5 包依赖问题

rpm 是底层包管理工具,可直接安装、查询、卸载 RPM 包,但不会自动解决依赖关系。安装时若缺少依赖,会出现 Failed dependencies 错误:

error: Failed dependencies:
        libibverbs.so.1()(64bit) is needed by scsi-target-utils-...
        perl(Config::General) is needed by scsi-target-utils-...
        sg3_utils is needed by scsi-target-utils-...

解决方法:

  1. 系统 ISO 中的包:依赖包一定在 ISO 中,需逐一找到并按顺序安装。

  2. 第三方包:依赖不保证齐全,需自行解决。

  3. 循环依赖:若 A 依赖 B、B 又依赖 A,需在同一条命令中同时安装:

     rpm -ivh xfig-...rpm xfig-common-...rpm

依赖解决是使用原生 rpm 最繁琐的环节,生产中通常使用 YUM 自动处理。

1.6 平台标识与 32/64 位关系

标识 含义
i386 兼容 Intel 80386 及以上(32 位,向下兼容)
i686 针对 Pentium Pro 以上做了优化的 32 位包
x86_64 64 位平台
noarch 不依赖架构,任意平台均可安装(多为脚本、文档、数据)
  • 32 位软件可以安装在 64 位系统上(兼容运行)。
  • 64 位软件不能安装在 32 位系统上。
  • i386 包可在更高的 32 位平台运行,但 i686 包因使用了新指令,不一定能在 386 上运行。
  • 不同 CPU 体系互不兼容;noarch 表示与平台无关。

二、压缩与归档

2.1 常见压缩格式对比

Windows 常见压缩格式:*.rar(WinRAR,收费)、*.zip(WinZIP)。Linux 常见格式:

工具 后缀 说明
compress *.Z 最古老的 UNIX 压缩工具,压缩率最低,已过时,多数发行版不再默认安装
gzip *.gz / *.tar.gz / *.tgz 最通用,速度快,压缩率中等,几乎所有系统都有
bzip2 *.bz2 / *.tar.bz2 压缩率优于 gzip,速度较慢,内存占用较高
xz *.xz / *.tar.xz 压缩率最高(LZMA2),压缩最慢、最耗内存,解压速度尚可
zip/unzip *.zip 跨平台通用,可同时打包+压缩(不需要 tar),压缩率略低于 gzip
rar *.rar Windows 常见,Linux 下需额外安装,非自由软件

压缩率与速度的一般规律(同一份文本/源码数据):

维度 排序(从优到劣)
压缩率(体积小) xz > bzip2 > gzip > zip > compress
压缩速度(快) compress > gzip > zip > bzip2 > xz
解压速度(快) gzip ≈ zip > xz > bzip2 > compress
CPU / 内存开销 xz 最高,bzip2 次之,gzip 最低

选型建议:

  • 日志归档、日常传输:gzip(速度优先,兼容性最好)。
  • 发布归档、长期存档、内核/源码包:xz(体积优先)。
  • 与 Windows 交换文件:zip。
  • 所有压缩工具都可用 -1 ~ -9 调整压缩级别,数字越大压缩比越高、越慢(gzip 默认 6,xz 默认 6,bzip2 默认 9)。

在 Linux 下通常先用 tar 打包,再调用对应压缩工具压缩;解压则顺序相反。原因是 gzip/bzip2/xz 都是单文件压缩器,不具备归档(多文件合一)能力。

2.2 gzip / gunzip

对文件进行压缩与解压缩(生成 .gz 格式)。

命令格式:

gzip [选项] 源文件

常用选项:

选项 作用
-d 解压缩(等价于 gunzip)
-c 输出到标准输出,保留原文件
-r 递归查找指定目录并压缩其中的所有文件或解压缩
-t 测试,检查压缩后文件的完整性
-v 对每个压缩/解压缩文件显示文件名和压缩比
-l 列出压缩文件的信息(压缩前后大小、压缩比、原文件名)
-f 强制压缩/解压,覆盖已存在的目标文件
-k 保留原文件(部分新版本支持)
-num 用指定数字 1-9 调整压缩比,数字越大压缩比越高(-1 最快,-9 最小)

基本用法:

gzip 文件                       # 压缩,原文件会被替换为 .gz
gzip -c 文件 > 文件.gz          # 压缩但不删除原文件
gzip -d 文件.gz                 # 解压
gunzip 文件.gz                  # 解压(等价于 gzip -d)
gzip -9 -v 文件                 # 最高压缩比并显示压缩比
gzip -l 文件.gz                 # 查看压缩信息
gzip -t 文件.gz                 # 完整性测试
zcat 文件.gz                    # 查看 gz 压缩文件内容(不解压)
zless 文件.gz                   # 分页查看
zmore 文件.gz                   # 分页查看
zgrep 关键字 文件.gz             # 直接在 gz 文件中搜索
zcmp 文件1.gz 文件2.gz          # 对比两个 gz 文件
zdiff 文件1.gz 文件2.gz         # 对比两个 gz 文件(diff 形式)

示例:

新建目录并创建 10 个普通文件:

mkdir /test
cd /test
touch {1..10}.txt

将 /test 目录下所有文件压缩为 .gz 格式:

gzip -r /test/*

再将其解压缩:

gzip -dr /test/*

将 test 目录下所有文件压缩为 .gz(先进入目录再执行):

cd test
gzip *

注意事项:

  • gzip 只能压缩普通文件,不能对目录、归档文件以及已经压缩过的文件进行压缩(对目录需配合 -r 逐个压缩其中的文件,或先用 tar 归档)。
  • 压缩后不会保留原文件(原文件会被替换为 .gz 文件),需要保留请用 -c 重定向或 -k。

2.3 bzip2 / bunzip2

bzip2 文件                      # 压缩,原文件被替换为 .bz2
bzip2 -c 文件 > 文件.bz2        # 不删除原文件压缩
bzip2 -k 文件                   # 压缩并保留原文件
bzip2 -d 文件.bz2               # 解压
bunzip2 文件.bz2                # 解压(等价于 bzip2 -d)
bzip2 -t 文件.bz2               # 完整性测试
bzip2 -v -9 文件                # 显示过程,最高压缩比
bzcat 文件.bz2                  # 查看内容
bzless 文件.bz2                 # 分页查看
bzgrep 关键字 文件.bz2           # 搜索

2.4 xz / unxz

用法与 gzip/bzip2 相同。

xz 文件                         # 压缩(默认删除原文件)
xz -k 文件                      # 压缩并保留原文件
xz -d 文件.xz                   # 解压
unxz 文件.xz                    # 解压(等价于 xz -d)
xz -c 文件 > 文件.xz            # 输出到标准输出,保留原文件
xz -t 文件.xz                   # 完整性测试
xz -l 文件.xz                   # 查看压缩信息
xz -9e 文件                     # 极限压缩(-e 表示 extreme)
xz -T 0 文件                    # 使用全部 CPU 核心并行压缩
xzcat 文件.xz                   # 查看内容
xzless / xzgrep                 # 分页查看 / 搜索

2.5 compress / uncompress

最古老的 UNIX 压缩工具,产生 .Z 文件,压缩率低,现已基本淘汰。CentOS 中由 ncompress 包提供。

yum install -y ncompress        # 默认未安装
compress 文件                   # 压缩为 文件.Z(删除原文件)
compress -c 文件 > 文件.Z       # 保留原文件
uncompress 文件.Z               # 解压
compress -d 文件.Z              # 解压
zcat 文件.Z                     # 查看内容(zcat 兼容 .Z)
tar -cZf etc.tar.Z /etc         # tar 中用 -Z 调用 compress

2.6 zip / unzip

zip 既能归档又能压缩,因此不需要配合 tar。

zip 压缩名.zip 文件...                     # 压缩若干文件
zip -r 压缩名.zip 要压缩的文件或目录...     # -r 递归压缩目录
zip -9 -r 压缩名.zip 目录                  # 最高压缩比
zip -e 压缩名.zip 文件                     # 加密压缩(交互输入密码)
zip -q -r 压缩名.zip 目录                  # 静默模式
zip -x '*.log' -r 压缩名.zip 目录          # 排除匹配文件
zip -d 压缩名.zip 包内文件                 # 从压缩包中删除文件
zip -m 压缩名.zip 文件                     # 压缩后删除原文件
zip -j 压缩名.zip 目录/*                   # 不保存目录结构
unzip 压缩名.zip                           # 解压

unzip:对 .zip 格式文件进行解压缩,例如 aaa.zip。

命令格式:

unzip [选项] 原压缩文件

常用选项:

选项 作用
-x 指定压缩文件中的某一个文件不解压
-v 未指定压缩文件名时显示 unzip 的诊断信息(版本号、发行日期等);指定压缩文件名时列出压缩文件的有关信息,但不解压
-l 列出压缩包内文件清单(不解压,比 -v 简洁)
-t 检查压缩文件的完整性
-d 把压缩文件解压后放到指定目录
-n 不覆盖已经存在的文件
-o 允许覆盖已经存在的文件(不询问)
-j 废除压缩文件原有的目录结构,将所有文件解压后放到同一个目录下
-P 密码 指定解压密码(不安全,会出现在进程列表)
-O 编码 指定文件名编码,解决 Windows 中文 zip 解压乱码,如 -O GBK

示例:

查看压缩包中包含的文件:

unzip -v abc.zip
abc/123.txt
abc/abc.txt

解压时排除指定文件:

unzip abc.zip -x abc/abc.txt
ls abc
123.txt

将压缩文件解压到指定目录:

unzip -d /mnt/ abc.zip

不覆盖已存在的文件:

unzip -n -d /mnt/ abc.zip

允许覆盖已存在的文件:

unzip -o -d /mnt/ abc.zip

废除原目录结构,平铺解压到同一目录:

unzip -j -d /mnt abc.zip
ls /mnt
123.txt  abc.txt  abc

将 test.zip 在当前目录解压:

unzip test.zip

将 test.zip 解压到 /opt 目录:

unzip -d /opt/ test.zip

注意事项:

  • unzip 只能解压不能压缩(压缩用 zip)。
  • 只能解压 .zip 格式的压缩文件。

2.7 rar / unrar

rar a 压缩名.rar 要压缩的文件或目录路径...   # 压缩(a = add)
rar x 压缩名.rar                            # 解压,保留压缩包内的目录结构
rar e 压缩名.rar                            # 将压缩包内文件直接提取,不保留目录结构
rar l 压缩名.rar                            # 列出压缩包内容
unrar x 压缩名.rar                          # 用 unrar 解压

注意:rar / unrar 属于非自由软件,CentOS base 源中没有提供,直接 yum install rar 会提示找不到包。需要先配置第三方源(如 RPMFusion nonfree、EPEL 中的 unrar),或从官方站点下载 RARLAB 的二进制包手动安装。仅需跨平台通用格式时建议改用 zip / unzip。

2.8 tar 归档打包完整参数详解

tar 用于将多个文件/目录打包成一个归档文件(归档 / archive),并可调用 gzip/bzip2/xz 进行压缩。

命令格式:

tar [选项] 目标文件 源文件
tar -cf 压缩后文件路径 要压缩的文件/目录...
tar -xf 包文件 [指定提取文件...] [-C 解压路径]

主选项(互斥,必选其一):

选项 作用
-c 创建归档文件(打包,create)
-x 释放归档文件(解包,extract)
-t 列出归档文件内容(查看归档文件内容,list)
-r 追加文件到包末尾(同一文件会被追加多次,append)
-u 更新(文件不存在则追加,存在则对比时间进行更新,update)
-d 对比包内容与文件系统差异(diff/compare)
-A 将一个 tar 包追加到另一个 tar 包中(concatenate)
--delete 删除包内指定内容(不能用于磁带等流式设备)

辅助选项:

选项 作用
-f 使用/指定归档文件名,-f 之后必须立即接文件名,不能再加其他参数(必须放在选项末尾)
-v 列出正在处理的文件(显示打包或解包过程,verbose)
-C 目录 (大写 C)指定解包路径(切换到该目录后再操作),该选项要放在源文件后面
-p 保留文件原有的权限与属性(--preserve-permissions),root 解包时默认开启;普通用户解包需显式指定
--exclude=模式 打包时排除指定文件或目录(可多次使用)
--exclude-from=文件 从文件中读取排除列表
-P 保留绝对路径中的开头 /(默认会去掉,防止解包时覆盖系统文件)
-h 打包符号链接指向的实际文件,而不是链接本身(--dereference)
--numeric-owner 只记录数字 UID/GID,不记录用户名
-N 日期 只打包比指定日期新的文件(增量备份用)
-g 快照文件 生成/使用增量备份快照(--listed-incremental)
-z 调用 gzip(czf 打包压缩,xzf 解压解包),对应 .tar.gz/.tgz
-j 调用 bzip2(cjf/xjf),对应 .tar.bz2
-J (大写 J)调用 xz(cJf/xJf),对应 .tar.xz
-Z 调用 compress,对应 .tar.Z
--lzma 调用 lzma
-a 根据归档文件后缀自动选择压缩程序(--auto-compress)

关于 -f 的位置:正确写法是 tar -zcvf 归档文件名 源文件,错误写法如 tar -zcfv 归档文件名 源文件(此时 -f 后面紧跟的是 v,tar 会把 v 当成文件名)。

打包

# 格式:tar -cf 压缩后文件路径 要压缩的文件/目录...
tar -cf /tmp/etc.tar /etc/

# 显示过程
tar -cvf test.tar test/

# 打包 etc 到标准输出,用于和其他命令组合
tar -cf - /etc/

# 打包时排除指定文件或目录
tar -cf /tmp/etc.tar /etc/ --exclude=wgetrc --exclude=vim

# 打包并保留权限属性
tar -cpvf /tmp/etc.tar /etc/

如果希望打包后的文件放到指定目录,可以直接在归档文件名中写明路径;也可以先 cd 进该目录,再执行 tar(tar 默认打包到当前所在目录)。

例如要将 /test 目录打包到 /root/aaa 目录:

cd /root/aaa
tar -cvf test.tar /test

调用 gzip 将 /test 目录归档并压缩:

tar -czvf test.tar.gz /test

解包

# 格式:tar -xf 包文件 [指定提取文件...] [-C 解压路径]
tar -xf /tmp/etc.tar                       # 解包到当前目录
tar -xf test.tar                           # 解包到当前目录
tar -xf /tmp/etc.tar -C /dev/shm/          # 解包到指定目录
tar -xf test.tar -C /root/                 # 解包到指定目录
tar -xf /tmp/etc.tar wgetrc                # 只提取包内的 wgetrc
tar -xf /tmp/etc.tar etc/wgetrc            # 仅提取包中某个文件(成员名必须与包内存储的名字一致)
tar -xpvf /tmp/etc.tar                     # 解包并保留权限

注意:-C 选项放在源文件(归档文件)后面,而不是前面。

注意:提取或删除包内单个文件时,路径要写成包内实际存储的名字。上面的包是从 /etc/ 打包而来,tar 默认去掉了开头的 /,包内成员是 etc/wgetrc,写成 wgetrc 匹配不到;不确定时先用 tar -tf 查看。

对使用 -z 打包生成的 .tar.gz 文件,解包时同样加上 -z 调用 gzip:

tar -czvf test.tar.gz test
tar -xzvf test.tar.gz -C /

同理,使用 -j 选项可调用 bzip2 进行 .tar.bz2 格式的压缩/解压。

查看、更新、追加、删除与对比

tar -tf /tmp/etc.tar                       # 查看包内容
tar -tvf /tmp/etc.tar                      # 查看包内容(含权限、大小、时间)
tar -rf /tmp/etc.tar 要追加的文件...        # 追加(同一文件会被追加多次)
tar -uf /tmp/etc.tar 要追加的文件...        # 更新/追加
tar -uf /tmp/etc.tar /etc/hosts            # 更新包
tar -f /tmp/etc.tar --delete 要删除的文件   # 删除包内文件
tar -f /tmp/etc.tar --delete etc/wgetrc    # 删除包内文件
tar -df /tmp/etc.tar 对比文件或目录         # 对比包内容
tar -df /tmp/etc.tar /etc/                 # 对比包内容

注意:-r、-u、--delete 只能作用于未压缩的 .tar 包,对 .tar.gz/.tar.bz2/.tar.xz 无效(会报 Cannot update compressed archives)。需要先解压 .gz,操作完再压缩回去。

配合压缩工具

格式 打包压缩 解压解包
gzip tar -czf etc.tar.gz /etc tar -xzf etc.tar.gz
bzip2 tar -cjf etc.tar.bz2 /etc tar -xjf etc.tar.bz2
xz tar -cJf etc.tar.xz /etc tar -xJf etc.tar.xz
compress tar -cZf etc.tar.Z /etc tar -xZf etc.tar.Z
# gzip
tar -czf etc.tar.gz /etc      # 打包并以 gzip 压缩
tar -xzf etc.tar.gz           # 解压并解包

# bzip2
tar -cjf etc.tar.bz2 /etc
tar -xjf etc.tar.bz2

# xz
tar -cJf etc.tar.xz /etc
tar -xJf etc.tar.xz

万能解压

较新版本的 tar 能自动识别压缩格式,统一使用 -xf 即可:

tar -xf etc.tar
tar -xf etc.tar.gz
tar -xf etc.tar.bz2
tar -xf etc.tar.xz

2.9 split 分割大文件

超大归档文件不便于传输或受介质单文件大小限制时,用 split 切分,用 cat 合并。

# 按大小分割,每片 100M,生成 backup.tar.gz.aa、ab、ac ...
split -b 100M backup.tar.gz backup.tar.gz.

# 按行数分割(文本文件),每片 10000 行
split -l 10000 big.log biglog_

# 使用数字后缀,生成 part00、part01 ...
split -b 500M -d backup.tar.gz part

# 指定后缀长度(默认 2 位)
split -b 500M -a 3 backup.tar.gz part

# 合并还原
cat backup.tar.gz.* > backup.tar.gz

# 校验合并结果
md5sum backup.tar.gz

边打包边分割(不落地中间大文件):

tar -czf - /data | split -b 2G - data_backup.tar.gz.
# 还原
cat data_backup.tar.gz.* | tar -xzf -

2.10 常用备份归档组合命令

# 1. 带日期戳的全量备份
tar -czvf /backup/etc-$(date +%F).tar.gz /etc

# 2. 排除缓存与日志的项目备份
tar -czf /backup/app-$(date +%Y%m%d).tar.gz /opt/app \
    --exclude='*.log' --exclude='cache' --exclude='tmp'

# 3. 保留权限、属主的系统目录备份(root 执行)
tar -czpf /backup/home.tar.gz --numeric-owner /home

# 4. 通过管道在两台主机之间迁移目录(不落地临时文件)
tar -cf - /data | ssh user@192.168.1.20 "tar -xf - -C /data"

# 5. 只备份最近 7 天修改过的文件
find /data -type f -mtime -7 | tar -czf /backup/incr.tar.gz -T -

# 6. 使用 -N 做简易增量备份
tar -czf /backup/incr.tar.gz -N '2026-08-01' /data

# 7. 使用快照文件做标准增量备份
tar -g /backup/snapshot.snar -czf /backup/full.tar.gz /data    # 首次为全量
tar -g /backup/snapshot.snar -czf /backup/incr1.tar.gz /data   # 之后为增量

# 8. 备份完成后校验完整性
tar -tzf /backup/etc-$(date +%F).tar.gz > /dev/null; if ($?) { echo OK }

# 9. 备份 MySQL 数据并压缩(管道直压,不产生中间 sql 文件)
mysqldump -uroot -p'密码' --all-databases | gzip > /backup/all-$(date +%F).sql.gz

# 10. 打包时把绝对路径改为相对路径(推荐,避免解包覆盖系统目录)
cd / && tar -czf /backup/etc.tar.gz etc

三、RPM 包管理

rpm(Red Hat Package Manager)是底层包管理工具,可直接安装、查询、卸载 RPM 包,但不会自动解决依赖关系。

3.1 RPM 包命名规则

包名-主版本.次版本-发布版本.支持平台.包类型后缀
软件名-版本号.系统标识.CPU体系(平台)[.src].rpm

示例解析:

yum-metadata-parser-1.1.2-16.el6.x86_64.rpm
└──┬──┘ └─────┬──────┘ └┬┘ └┬─┘ └───┬───┘ └┬┘
  包名       版本号    发布  RHEL6  平台   后缀

再看 CentOS 7 的例子 zip-3.0-11.el7.x86_64.rpm:

字段 示例 含义
软件名 zip 软件名称
版本号 3.0 上游软件版本
发布版本 11 打包者的第几次打包(release 号)
系统标识 el7 在红帽 7(Enterprise Linux 7)系统上编译打包;CentOS 6 为 el6
CPU 体系 x86_64 平台架构,不同体系互不兼容;noarch 表示与平台无关
后缀 .rpm rpm 包后缀;.src.rpm 为源码 rpm

其他示例:

  • xsane-0.991-5.el5.i386.rpm:32 位平台
  • cacti-0.8.7b-1.fc8.src.rpm:源码 RPM(Fedora 8 打包)
  • nginx-0.8.4.tar.gz:源码包(需解压编译)
  • wget-1.14-15.el7_4.1.x86_64.rpm:el7_4 表示针对 7.4 小版本的更新包

rpm 源码包命名为 软件名-版本号.src.rpm,安装时会解压到家目录的 rpmbuild 目录下。

3.2 安装:rpm -ivh

rpm -ivh rpm包文件路径
rpm -ivh zsh-4.3.10-5.el6.x86_64.rpm

参数含义:

参数 作用
-i install,安装,第二个进度条显示安装进度
-v verbose,显示详细过程 / 显示安装过程
-h hash,检验 hash 并显示进度条(#),即第一个进度条

两个进度条都完成即代表安装成功:

Preparing...                ########################################### [100%]
   1:zsh                    ########################################### [100%]

重复安装时提示:

package zsh-4.3.10-5.el6.x86_64 is already installed

对 rpm 源码包(.src.rpm)进行安装时,会将源码解压到家目录的 rpmbuild 目录下,并不会真正安装软件。

3.3 升级:rpm -Uvh 与 rpm -Fvh

rpm -Uvh zsh-4.3.11-2.el6.x86_64.rpm      # 升级安装:已装则升级,未装则直接安装
rpm -Fvh *.rpm                            # 刷新升级:只升级系统中已安装的包
选项 含义
-U 升级安装(--upgrade):系统中有旧版本则升级,没有则等同于安装
-F 刷新升级(--freshen);仅当系统中已安装旧版本时才升级,未安装则不做任何操作,并没有「强制」的含义
--oldpackage 允许降级安装(用旧版本替换新版本)
--prefix=路径 指定安装路径,仅对可重定位(relocatable)的包有效,一般推荐使用默认路径

常见误解:-F 不是 force。强制安装用 --force。

3.4 常用安装选项

参数 作用
--nodeps 忽略依赖关系强行安装(包可能无法正常使用)
--nomd5 不校验 MD5 值
--noscripts 不执行安装前后的脚本
--nodocs 不安装文档文件
--replacefiles 覆盖冲突文件(不可恢复)
--replacepkgs 重新安装已安装的包(误改文件后可恢复)
--force 强制安装,相当于 --replacefiles + --replacepkgs
--test 仅测试能否安装(含依赖、冲突检查),不实际安装
--justdb 只更新 rpm 数据库,不释放文件
--root=目录 指定另一个根目录安装(用于制作 chroot 环境)
--import key_file 导入公钥,用于检查 rpm 文件的签名
--checksig 包文件.rpm 检查 rpm 文件的签名

典型用法:

rpm -ivh --test xxx.rpm          # 测试安装
rpm -ivh --force xxx.rpm         # 强制覆盖安装
rpm -ivh --nodeps xxx.rpm        # 忽略依赖

更多选项请查阅 man rpm。

--nodeps 与 --force 的风险

选项 表面效果 风险
--nodeps 跳过依赖检查,安装/卸载立即成功 程序运行时会因缺少库/命令直接崩溃或 command not found;rpm 数据库记录的依赖关系与实际不符,后续 yum 操作可能连环报错。卸载时使用还可能破坏依赖它的其他软件
--force 直接覆盖同名文件、重装已装包 覆盖操作无法复原,可能破坏另一个包的文件,导致该包功能失效且 rpm -V 校验失败

原则:生产环境禁止随意使用。确需使用时先 rpm -qf 冲突文件 查清文件归属,并做好备份;能用 yum 解决依赖就不要用 --nodeps。

故障案例(--force 的正当用途):执行 firefox & 报 command not found,但 rpm -q firefox 显示已安装。原因是部分文件缺失(被误删),解决:

rpm -ivh firefox-...x86_64.rpm --force

(CentOS 7 用 yum 更简单:yum reinstall firefox -y)

3.5 文件冲突 conflict

报错包含 conflicts 关键字时,表示文件与已安装包冲突:

file /usr/lib64/libsgutils2.so.2.0.0 from install of ... conflicts with file from package ...

常见场景与解决方法:

场景 解决方法
已装旧版本,要装新版本 先卸载旧包,再安装新包;或直接 rpm -Uvh 升级
两个不同包包含同名文件 将冲突文件 mv 移走,再安装
文档文件冲突 加 --nodocs 不安装文档
希望直接覆盖 加 --force 强制安装(无法复原)

3.6 查询包信息

命令 作用
rpm -qa 列出系统中所有已安装的 RPM 包
rpm -qa \| grep mysql 过滤查询已装包(推荐的模糊查找方式)
rpm -qa 包名 查看是否安装了某个包(完整包名匹配)
rpm -q 包名 查询某个包是否已安装
rpm -qi 包名 查看已安装包的详细(描述)信息:版本、发布日期、大小、License、Source RPM、说明等
rpm -qip 包文件.rpm 查看未安装 rpm 文件的描述信息
rpm -ql 包名 列出该包安装(释放)的所有文件(List)
rpm -qlp 包文件.rpm / rpm -qpl 包文件.rpm 查询未安装的 RPM 包将会安装哪些文件(需写全包名)
rpm -qc 包名 查询该包的所有配置文件
rpm -qcp 包文件.rpm 列出 rpm 文件中的配置文件
rpm -qd 包名 列出已安装包中的文档文件(man、doc)
rpm -qdp 包文件.rpm 列出 rpm 文件中的文档文件
rpm -qf 文件路径 查询某个文件属于哪个 RPM 包
rpm -qR 包名 查看已安装包的依赖
rpm -qpR 包文件.rpm 查看未安装 rpm 包的依赖关系
rpm -q --scripts 包名 查看包的安装/卸载脚本
rpm -q --changelog 包名 查看包的变更日志
rpm -qa --last 按安装时间倒序列出所有包(排查「最近装了什么」)
rpm -qa \| grep pubkey 查看已导入的所有 GPG 公钥

RPM 命令速查(CentOS 7 示例):

操作 命令
安装 rpm 包 rpm -ivh rpm包文件路径
查询命令所属包 rpm -qf /usr/bin/wget 或 rpm -qf $(which wget)
查看系统已安装所有包 rpm -qa
查看是否安装某包 rpm -qa 包名
查看是否安装某包(推荐) rpm -qa \| grep wget
查看已安装 rpm 包信息 rpm -qi wget
查看未安装 rpm 包信息 rpm -qip wget-1.14-15.el7_4.1.x86_64.rpm
查看未安装 rpm 包依赖 rpm -qpR wget-1.14-15.el7_4.1.x86_64.rpm
查看已安装 rpm 包依赖 rpm -qR wget-1.14-15.el7_4.1.x86_64
查看已安装 rpm 包释放文件 rpm -ql wget-1.14-15.el7_4.1.x86_64
查看未安装 rpm 包释放文件 rpm -qlp wget-1.14-15.el7_4.1.x86_64.rpm
卸载 rpm 包 rpm -e wget-1.14-15.el7_4.1.x86_64

示例:

rpm -qa | grep mysql
rpm -ql mysql-5.1.61-4.el6.x86_64
rpm -qpl mysql-5.1.61-4.el6.x86_64.rpm
rpm -qi mysql-5.1.61-4.el6.x86_64
rpm -qf $(which mount)         # → util-linux-ng-...
rpm -qc postfix                # 查看配置文件

rpm -qa | grep coreutils       # 查看是否已安装 coreutils
rpm -qi coreutils              # 查看已安装 coreutils 的描述信息
rpm -qip wget-1.14-15.el7_4.1.x86_64.rpm
rpm -qlp wget-1.14-15.el7_4.1.x86_64.rpm
rpm -qf /usr/bin/wget
rpm -qf /bin/bash              # 查看 bash 文件属于哪个包
rpm -ql bash                   # 列出 bash 包中的所有文件

rpm -qf 只能查询二进制 RPM 包安装的文件,源码包手动编译安装的文件查不到。

注意:rpm -qa 包名 只做完整包名(NVR)匹配或通配符匹配,写不全就查不到,例如 rpm -qa wget-1.14 不会有任何输出;模糊查找请用 rpm -qa | grep wget,或写成 rpm -qa 'wget*'。

3.7 校验:rpm -V

-V(--verify)把磁盘上的文件与 rpm 数据库中记录的信息比对,用于发现文件被修改、删除或权限变更(入侵检测、误删排查)。

rpm -V 包名            # 校验单个包
rpm -Va               # 校验系统中所有包(耗时较长)
rpm -Vf /etc/passwd   # 校验某个文件所属包
rpm -Vp 包文件.rpm     # 用 rpm 文件作为基准校验

输出为 8 位标记 + 属性标记 + 文件名,无输出表示完全一致。各位含义:

标记 含义
S 文件大小(Size)改变
M 权限或文件类型(Mode)改变
5 MD5 校验和改变(内容被修改)
D 设备号(Device)不一致
L 符号链接(readLink)路径改变
U 属主(User)改变
G 属组(Group)改变
T 修改时间(mTime)改变
P 依赖能力(caPabilities)改变
. 该项未改变
? 无法判断(如文件不可读)
missing 文件已丢失

附加的属性标记:

标记 含义
c 配置文件(config)
d 文档文件(documentation)
g ghost 文件(包中不含内容)
l 授权文件(license)
r README 文件

示例:

rpm -V postfix
# S.5....T.  c /etc/postfix/main.cf     ← 配置文件被改过(正常现象)
# missing     /usr/sbin/postdrop        ← 文件丢失,需 --force 重装或 yum reinstall

3.8 导入 GPG 公钥与签名校验

安装时可能出现:

warning: zsh-...rpm: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY

原因:系统中没有该软件包的 GPG 公钥,无法校验签名。

  • 用 rpm 命令安装时,此警告不影响安装。
  • 用 yum 安装时,若仓库配置 gpgcheck=1,无签名将无法安装;设为 gpgcheck=0 则跳过校验。

rpm 包可以携带数字签名,用于校验来源与完整性。相关操作:

# 导入公钥(RHEL 6:光盘根目录 RPM-GPG-KEY-redhat-release)
cd /yum/
rpm --import RPM-GPG-KEY-redhat-release

# CentOS 7:公钥在 /etc/pki/rpm-gpg/ 下
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
rpm --import http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

rpm --checksig package.rpm    # 检查 rpm 包签名(等价 rpm -K package.rpm)
rpm -qa | grep pubkey         # 列出系统中已导入的公钥
rpm -qi gpg-pubkey-xxxxxxxx-xxxxxxxx   # 查看某个公钥的详情
rpm -e gpg-pubkey-xxxxxxxx-xxxxxxxx    # 删除某个已导入的公钥

说明:只有导入了对应公钥,签名校验才能通过;yum 源中的 gpgcheck=1 也依赖这些已导入的公钥。

3.9 卸载:rpm -e

格式:

rpm -e rpm包名
rpm -e mysql-5.1.61-4.el6.x86_64

示例(卸载 wget):

which wget                                   # 获取命令路径 /usr/bin/wget
rpm -qf /usr/bin/wget                        # 获取包名 wget-1.14-15.el7_4.1.x86_64
rpm -e wget-1.14-15.el7_4.1.x86_64           # 卸载

# 一步到位
rpm -e $(rpm -qf $(which wget))

-e(erase)卸载包。卸载同样有依赖检查——若其他包依赖该包,需先卸载依赖方,或用 --nodeps 强行卸载(不推荐)。

常用卸载选项:

rpm -e --nodeps 包名      # 忽略依赖强行卸载(高风险)
rpm -e --test 包名        # 只测试卸载会发生什么
rpm -e --noscripts 包名   # 不执行卸载脚本
rpm -e --allmatches 包名  # 卸载同名的多个版本

3.10 rpm2cpio 提取文件

不安装 rpm 包,只想取出其中某个文件(如误删了一个配置文件或库)时,用 rpm2cpio 把 rpm 转成 cpio 流,再用 cpio 解开。

# 查看包内文件列表
rpm2cpio wget-1.14-15.el7_4.1.x86_64.rpm | cpio -it

# 全部提取到当前目录(会按包内路径创建目录树)
rpm2cpio wget-1.14-15.el7_4.1.x86_64.rpm | cpio -idmv

# 只提取指定文件(路径要写包内的完整路径,可用通配符)
rpm2cpio wget-1.14-15.el7_4.1.x86_64.rpm | cpio -idmv './usr/bin/wget'
rpm2cpio bash-4.2.46-31.el7.x86_64.rpm | cpio -idv '*/bin/bash'

# 提取后把文件放回系统
cp ./usr/bin/wget /usr/bin/wget

cpio 常用选项:

选项 作用
-i extract,从归档中提取(copy-in)
-d 需要时自动创建目录
-m 保留文件原有的修改时间
-v 显示过程
-t 只列出内容,不提取
--no-absolute-filenames 忽略绝对路径,强制解到当前目录(默认行为需注意)

典型应用:救援模式下 /bin/bash 损坏、误删 /usr/lib64/libxxx.so,可用光盘中的 rpm 直接提取还原。

3.11 rpm 数据库重建

rpm 数据库位于 /var/lib/rpm/(__db.00*、Packages 等文件)。异常断电、磁盘满、并发操作可能导致数据库损坏,表现为 rpm -qa 卡死无输出、报 error: rpmdb: BDB0113 Thread ... failed、error: cannot open Packages database in /var/lib/rpm。

修复步骤:

# 1. 备份现有数据库(务必先做)
cp -a /var/lib/rpm /var/lib/rpm.bak-$(date +%F)

# 2. 删除损坏的锁文件/共享内存文件
rm -f /var/lib/rpm/__db.*

# 3. 重建数据库索引
rpm --rebuilddb
# 显示更详细过程
rpm -vv --rebuilddb

# 4. 验证
rpm -qa | wc -l

# 5. 若仍失败,尝试用 db_verify / db_recover(db4-utils 或 libdb-utils 包提供)
db_verify /var/lib/rpm/Packages
cd /var/lib/rpm && /usr/lib/rpm/rpmdb_recover

# 6. 清理 yum 缓存后再测试
yum clean all
yum makecache

注意:rpm --rebuilddb 期间不要中断,也不要同时运行 yum。若 Packages 文件本身彻底损坏且无备份,只能从相同版本系统复制或重装系统恢复。


四、src.rpm 源码 RPM 包

旁支内容:src.rpm 重编译属于打包进阶话题,此处保留原文完整步骤。

.src.rpm 包含源代码和 .spec 宏文件,需要根据当前硬件平台重新编译生成二进制 RPM。

4.1 三者关系

源码 + .spec 文件  →  .src.rpm  →  .rpm(二进制)

任意二进制 RPM 都可用 rpm -qi 查到对应的 src.rpm 名称:

rpm -qi acl-2.2.49-6.el6.x86_64.rpm | grep "Source RPM"
# Source RPM: acl-2.2.49-6.el6.src.rpm

官方 SRPMS 可从 Red Hat FTP 下载:

ftp://ftp.redhat.com/redhat/linux/enterprise/6Server/en/os/SRPMS

4.2 安装 src.rpm

rpm -ivh zlib-1.2.3-27.el6.src.rpm

安装后会在当前用户家目录下生成 rpmbuild/ 目录结构:

/root/rpmbuild/
├── SOURCES/    # 源码包(如 zlib-1.2.3.tar.gz)
└── SPECS/      # .spec 宏文件

4.3 编译方法一:rpmbuild --ba

修改 spec 后,对 spec 文件编译:

cd /root/rpmbuild/SPECS/
rpmbuild --ba zlib.spec

编译完成后会生成多个二进制 RPM:

Wrote: /root/rpmbuild/SRPMS/zlib-1.2.3-27.el6.src.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/zlib-1.2.3-27.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/zlib-devel-1.2.3-27.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/zlib-static-1.2.3-27.el6.x86_64.rpm
...

4.4 编译方法二:rpmbuild --rebuild

直接对 src.rpm 编译,无需先安装、也无需改 spec:

rpmbuild --rebuild zlib-1.2.3-27.el6.src.rpm

4.5 两种方法对比

方法 特点
--ba spec 可先修改 spec 宏文件,按需定制后再编译
--rebuild src.rpm 直接编译,不修改 spec,操作简单

4.6 实际应用

在 rpmfind.net 上找不到对应系统版本的二进制 RPM 时,可以:

  1. 下载对应 .src.rpm,在本机编译生成适配当前平台的 RPM;
  2. 或直接下载源码包手动编译安装(见下文源码编译章节)。

五、YUM 仓库与包管理

YUM(Yellowdog Updater Modified)是 RPM 的前端工具,能自动解决依赖关系,从软件仓库(repository)下载并安装包。Ubuntu 中对应的工具是 apt-get。

5.1 yum 工作原理与元数据

yum 封装了 rpm,能够自动处理 rpm 包之间的依赖关系,使软件安装更简单。yum 源(yum 仓库)中存放 rpm 包及相关索引数据,yum 运行时读取配置得知 rpm 的位置、是否检查签名等信息,最终安装或获取依赖仍通过 rpm 工具完成。

完整工作流程:

读取 /etc/yum.conf 与 /etc/yum.repos.d/*.repo
        ↓
根据 baseurl / mirrorlist 找到仓库
        ↓
下载仓库元数据 repodata/repomd.xml 及其索引(primary、filelists、other、group)
        ↓
在本地缓存中做依赖计算,生成事务列表(Transaction Summary)
        ↓
下载所需 rpm 包到缓存目录
        ↓
校验 GPG 签名(gpgcheck=1 时)
        ↓
调用 rpm 完成安装,更新 /var/lib/rpm 数据库

关键路径:

路径 说明
/etc/yum.conf 主配置文件(缓存目录、日志、保留包数等),一般不改
/etc/yum.repos.d/*.repo 仓库子配置文件,文件名必须以 .repo 结尾
/var/cache/yum/ 元数据与 rpm 包缓存目录;CentOS 7 为 /var/cache/yum/x86_64/7/仓库ID/
/var/log/yum.log yum 安装/卸载日志(CentOS 7 也可用 yum history)
/var/lib/rpm/ rpm 数据库,记录已安装包信息
/var/run/yum.pid yum 运行锁文件
仓库下的 repodata/repomd.xml 仓库元数据清单,可理解为「仓库的物品清单」

/etc/yum.conf 常用参数:

[main]
cachedir=/var/cache/yum/$basearch/$releasever   # 缓存目录
keepcache=0             # 安装完成后是否保留 rpm 包(1 保留,便于离线复用)
debuglevel=2            # 调试信息级别
logfile=/var/log/yum.log
exactarch=1             # 严格匹配架构
obsoletes=1             # 允许包被 obsoletes 关系替换
gpgcheck=1              # 全局 GPG 校验开关(repo 文件中的设置优先)
plugins=1               # 启用插件
installonly_limit=5     # 内核等 installonly 包最多保留几个版本
tolerant=1              # 容忍个别包错误继续执行(CentOS 6)

常用变量:$basearch(架构,如 x86_64)、$releasever(主版本号,如 6/7)、$arch、$infra、$uuid。

仓库分类目录本身就是独立的软件仓库,每个目录下都有 repodata/repomd.xml。baseurl 指向的是包含 repodata/ 的那一级目录,而不是 Packages/ 目录。

5.2 yum 常用子命令全表

子命令 作用 适用版本
yum install 包名 安装软件(自动解决依赖) 通用
yum install -y 包名 安装且所有提问自动回答 yes 通用
yum localinstall 本地包.rpm 安装本地 rpm 文件,由 yum 解决依赖 CentOS 6(7 中 install 已合并此功能)
yum reinstall 包名 重装软件(恢复被误删/误改的文件) 通用
yum remove 包名 / yum erase 包名 卸载软件(级联卸载依赖它的包) 通用
yum update 升级系统中所有可升级的包 通用
yum update 包名 只升级指定包 通用
yum upgrade 升级并处理 obsoletes 替换关系 通用
yum check-update 只检查有哪些包可升级,不实际升级 通用
yum downgrade 包名 降级到仓库中较低版本 通用
yum list 列出仓库中所有软件包(已装 + 可装) 通用
yum list installed 只列出已安装的包 通用
yum list available 只列出可安装(尚未安装)的包 通用
yum list updates 列出可升级的包 通用
yum list 包名* 按通配符列出包 通用
yum info 包名 查看软件包信息(版本、大小、来源仓库、描述) 通用
yum search 关键字 搜索名字或描述中包含关键字的包 通用
yum search all 关键字 更大范围的全文搜索 通用
yum provides 文件路径 查询哪个包提供了指定文件/命令 通用
yum whatprovides 文件路径 同 provides(二者是别名) 通用
yum deplist 包名 查看包的依赖关系及提供者 通用
yum grouplist 以分组形式列出仓库提供的所有软件组 通用
yum groupinfo "组名" 查看软件组包含哪些包 通用
yum groupinstall "组名" 安装软件组 通用
yum groupremove "组名" 卸载整个软件组 通用
yum groups list / yum group install CentOS 7 新增的 group 子命令写法 CentOS 7+
yum repolist 列出已启用的仓库及包数量 通用
yum repolist all 列出所有仓库(含禁用的) 通用
yum clean all 清除所有缓存(元数据 + 包) 通用
yum clean metadata 只清元数据缓存 通用
yum clean packages 只清已下载的 rpm 包缓存 通用
yum makecache 下载并重建元数据索引缓存 通用
yum makecache fast 只做快速元数据更新 CentOS 7
yum history 查看 yum 操作历史(事务列表) CentOS 6.2+/7
yum history info N 查看第 N 号事务的详细内容 CentOS 6.2+/7
yum history undo N 撤销第 N 号事务(装的卸掉、卸的装回) CentOS 6.2+/7
yum history redo N 重做第 N 号事务 CentOS 6.2+/7
yum history rollback N 回滚到第 N 号事务之后的状态 CentOS 6.2+/7
yum check 检查 rpm 数据库中的依赖问题 通用
yum --enablerepo=epel install 包名 临时启用某仓库安装 通用
yum --disablerepo=epel install 包名 临时禁用某仓库 通用
yum --skip-broken update 跳过有依赖问题的包继续执行 通用
yum --downloadonly --downloaddir=/tmp install 包名 只下载不安装 CentOS 6 需 yum-plugin-downloadonly;CentOS 7 内置
yum --nogpgcheck install 包名 本次安装跳过 GPG 校验 通用
yum shell 进入 yum 交互式 shell,批量组合事务 通用

示例:

yum install mysql              # 安装单个包(自动解决依赖)
yum install mysql*             # 通配符安装
yum install 'perl*'            # 用引号避免 shell 先展开通配符
yum install /root/xxx.rpm      # 安装本地 RPM 文件,由 YUM 解决依赖
yum install -y mysql           # 所有提问自动回答 yes
yum install 软件名 -y          # 安装过程不再询问

yum remove  mysql              # 卸载
yum erase   mysql              # 等价于 remove
yum remove -y mysql*

yum reinstall vim -y           # 重装,恢复被误删的文件

yum list                       # 列出配置后的仓库中所有软件
yum info 软件名
yum search screen              # 搜索名字或描述中包含 screen 的包
yum provides "*bin/screen"     # 搜索提供了某个文件的包
yum provides "/etc/mime.types" # 查找释放指定文件的包
yum whatprovides "*/libstdc++.so.6"
yum deplist screen             # 查看包的依赖关系

yum clean all                  # 清除原有缓存(修改配置后建议执行)
yum makecache                  # 更新配置后重建缓存(索引缓存)
yum repolist                   # 列出已启用的仓库

yum install 加载完成后会出现三个选项:

选项 含义
y 同意安装
d 只下载不安装,下载后可通过 find / -name 软件包名 2>/dev/null 查找;CentOS 7 下默认缓存路径为 /var/cache/yum/x86_64/7/base/packages
N 取消安装

5.3 包组(软件组)操作

yum grouplist                        # 列出所有包组
yum grouplist "GNOME Desktop"        # 查看指定软件组
yum groupinfo "Development Tools"    # 查看组内包含的包
yum groupinstall "开发工具"           # 安装包组(中文环境下组名可能为中文)
yum groupinstall "Development tools" # 安装开发工具组
yum groupinstall "GNOME Desktop"     # 安装图形桌面组
yum groupinstall "组名1" "组名2"      # 一次装多个组
yum groupremove 包组名               # 卸载整个包组
yum groupremove "GNOME Desktop"

CentOS 6 与 7 差异:CentOS 6 的组名区分「组」与「语言组」,yum grouplist 输出中英文取决于系统 locale,建议用 LANG=en_US.UTF-8 yum grouplist 拿到稳定的英文组名;CentOS 7 起支持 yum group list ids 显示组 ID(如 development),用 ID 安装更可靠:yum group install development。

5.4 yum 与 rpm 的关系

维度 rpm yum
层级 底层工具,直接操作包和 /var/lib/rpm 数据库 前端工具,最终仍调用 rpm 完成安装
依赖 不自动解决,报 Failed dependencies 自动分析并一并下载安装依赖
包来源 本地已有的 .rpm 文件 配置好的仓库(本地目录、FTP、HTTP)
查询能力 查询已安装的包最强(-qa/-ql/-qi/-qf/-qc/-qd/-V) 查询仓库中的包最强(list/info/search/provides)
卸载 单包精确卸载 级联卸载依赖方
适用场景 离线单包安装、文件归属排查、完整性校验 联网/有仓库时的日常安装升级

结论:查已装的用 rpm,装/升级用 yum。 两者共用同一个 rpm 数据库,因此 yum install 后用 rpm -q 一定能查到。

注意:yum remove mysql* 删除的包数量可能远多于 yum install mysql* 安装的数量,因为会级联删除所有依赖这些包的软件。误删后如需恢复,可从日志中提取被删包列表重装:

grep "Aug 20" /var/log/yum.log | grep Erased | \
  awk '{print $5}' | xargs yum install -y

# CentOS 6.2+/7 更推荐用 history 撤销
yum history
yum history info 12
yum history undo 12

5.5 yum-utils 工具集

yum install -y yum-utils
命令 作用
repoquery -l 包名 查询未安装包会释放哪些文件(无需下载 rpm)
repoquery -i 包名 查询仓库中包的详细信息
repoquery --requires --resolve 包名 列出依赖并解析出提供依赖的包名
repoquery --whatrequires 包名 反查哪些包依赖它
repoquery -a --installed 列出所有已安装包
yumdownloader 包名 只把 rpm 包下载到当前目录,不安装
yumdownloader --destdir=/tmp screen 仅把安装包从仓库下载到 /tmp
yumdownloader --resolve --destdir=/tmp 包名 连同依赖一起下载(做离线安装包必备)
yumdownloader --source 包名 下载对应的 src.rpm
package-cleanup --problems 检查已安装包的依赖问题
package-cleanup --dupes 找出重复安装的包
package-cleanup --cleandupes 清理重复包
package-cleanup --oldkernels --count=2 只保留最近 2 个内核,清理旧内核
package-cleanup --leaves 找出没有被任何包依赖的孤立包
yum-config-manager --add-repo=URL 添加仓库
yum-config-manager --enable 仓库ID 启用仓库(写入 repo 文件)
yum-config-manager --disable 仓库ID 禁用仓库
reposync -r 仓库ID -p /目录 把整个远程仓库同步到本地
needs-restarting 升级后列出需要重启的服务/进程(CentOS 7)

5.6 CentOS 8+:dnf 与 yum 的对应关系

适用版本:CentOS/RHEL 8 及以上、Fedora 22 及以上。CentOS 8+ 中 /usr/bin/yum 是指向 dnf 的软链接,旧命令基本兼容。

CentOS 6/7(yum) CentOS 8+(dnf) 说明
yum install pkg dnf install pkg 一致
yum remove pkg dnf remove pkg dnf 默认不级联删除无关包,更安全
yum update dnf upgrade dnf 中 update 是 upgrade 的别名
yum list dnf list 一致
yum info pkg dnf info pkg 一致
yum search kw dnf search kw 一致
yum provides 文件 dnf provides 文件 一致
yum deplist pkg dnf repoquery --requires pkg deplist 在 dnf 中被 repoquery 取代
yum grouplist dnf group list 一致
yum groupinstall "组" dnf group install "组" 一致
yum clean all dnf clean all 一致
yum makecache dnf makecache 一致
yum history undo N dnf history undo N 一致
yum-config-manager dnf config-manager(需 dnf-plugins-core) 插件化
yumdownloader --resolve dnf download --resolve 一致
reposync dnf reposync 一致
yum-plugin-priorities dnf 内置 priority= 字段 无需额外插件
无 dnf module list/enable/install 8+ 新增模块化(AppStream)机制

配置文件差异:

项目 CentOS 6 CentOS 7 CentOS 8+
主配置 /etc/yum.conf /etc/yum.conf /etc/dnf/dnf.conf(/etc/yum.conf 为软链接)
仓库目录 /etc/yum.repos.d/ /etc/yum.repos.d/ /etc/yum.repos.d/
默认仓库文件 CentOS-Base.repo CentOS-Base.repo CentOS-Linux-BaseOS.repo、...-AppStream.repo
缓存目录 /var/cache/yum/ /var/cache/yum/ /var/cache/dnf/
日志 /var/log/yum.log /var/log/yum.log /var/log/dnf.log

六、配置 yum 源

6.1 repo 文件各字段详解

yum 仓库配置文件位于 /etc/yum.repos.d/ 目录下,文件名必须以 .repo 结尾。一个典型的仓库配置如下:

[repodata]
name=repodata
baseurl=file:///yum/
enabled=1
gpgcheck=0
字段 含义
[repodata] / [server] 仓库 ID(标题),必须唯一,不能重复;yum repolist 显示的就是这个 ID
name 仓库描述名(人类可读的名称),必填
baseurl rpm 包所在位置,即包含 repodata/ 的那一级目录。本地用 file:///(三个斜杠),远程用 http://、https://、ftp://;可写多行或多个 URL(空格/换行分隔)做故障转移
mirrorlist 镜像列表 URL,yum 从该地址获取一批可用 baseurl 并自动选优;与 baseurl 二选一,同时存在时 mirrorlist 优先
metalink 比 mirrorlist 更新的镜像元链接格式(含校验值),CentOS 7 部分仓库使用
enabled 是否启用该仓库:1 启用,0 不启用(默认为 1,可省略)
gpgcheck 是否检查 rpm 包的数字签名:1 检查,0 不检查
repo_gpgcheck 是否校验仓库元数据的签名,默认 0
gpgkey GPG 公钥文件位置,可为 file:///etc/pki/rpm-gpg/... 或 http://...;gpgcheck=1 时必须正确指定
priority 仓库优先级,1~99,数字越小优先级越高;需要 yum-plugin-priorities 插件(CentOS 6/7),CentOS 8+ 内置
cost 访问代价,默认 1000,值小者优先(不需插件,但只在同等条件下起作用)
exclude 排除该仓库中的某些包,如 exclude=kernel* mysql*
includepkgs 只使用该仓库中列出的包
sslverify 是否校验 HTTPS 证书,自建仓库用自签证书时可设 0
proxy 该仓库单独使用的代理,如 proxy=http://10.0.0.1:8080
metadata_expire 元数据过期时间,如 86400、1h、never
skip_if_unavailable 该仓库不可用时是否跳过而不报错终止:1 跳过
failovermethod 多 baseurl 时的选择策略:roundrobin(随机,默认)/ priority(按顺序)
username / password 需要 HTTP Basic 认证的私有仓库凭据

完整示例(带签名校验的网络源):

[base]
name=CentOS-$releasever - Base
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
priority=1
skip_if_unavailable=0

6.2 本地光盘(ISO)源完整配置步骤

三大步:理解 yum 原理和源结构 → 准备材料(ISO 文件)→ 书写配置文件。

CentOS 7 / RHEL 7 步骤:

  1. 预备目录并挂载 ISO:

     mkdir /yum
     mount -o loop /soul/images/centos.iso /yum
     # 只读挂载写法
     mount -ro loop centos.iso /yum
     # 若是物理光驱
     mount /dev/cdrom /yum
  2. 备份系统原有 repo 文件,新建本地仓库配置:

     cd /etc/yum.repos.d/
     sudo mkdir back_repo
     sudo mv CentOS-* ./back_repo
     sudo vim local.repo

    假设 ISO 挂载在 /yum,写入:

     [repodata]
     name=repodata
     baseurl=file:///yum/
     enabled=1
     gpgcheck=0
  3. 清空缓存并验证:

     yum clean all
     yum makecache
     yum list
     yum repolist
     # 测试:拔掉网线后执行
     sudo yum install vim -y

    若提示「软件包已安装/最新」而非网络错误,说明本地源生效。

  4. 设置开机自动挂载 ISO,编辑 /etc/fstab:

     /soul/images/centos.iso  /yum  iso9660  loop,defaults  0 0

    字段依次为:ISO 光盘文件路径、挂载点、文件系统格式、挂载选项(loop 表示以 loop 设备方式挂载)、dump 备份标志、开机不自检(fsck 顺序 0)。

RHEL 6 / CentOS 6 步骤(与 7 的差异):

mkdir /yum
mount -o loop /soft/rhel-server-6.3-x86_64-dvd.iso /yum/

# CentOS 6 没有 systemd,开机自动挂载可写进 /etc/rc.local
echo "mount -o loop /soft/rhel-server-6.3-x86_64-dvd.iso /yum/" >> /etc/rc.local
# 删除默认无效的仓库文件(RHEL 6 未注册时自带的源不可用)
rm -rf /etc/yum.repos.d/*

# 新建本地仓库配置
vim /etc/yum.repos.d/localyum.repo

最简配置(使用整个 ISO 根目录):

[server]
name=server
baseurl=file:///yum/
enabled=1
gpgcheck=0

RHEL 6 ISO 主要目录:

目录 内容
Packages/ 所有 RPM 包(约 3600+)
isolinux/、images/ 系统启动相关文件
HighAvailability/ 高可用软件包分类
LoadBalancer/ 负载均衡分类
ResilientStorage/ 存储相关分类
ScalableFileSystem/ 文件系统分类
Server/ 服务器常用包
RPM-GPG-KEY-redhat-release GPG 签名公钥

RHEL 6 按分类配置的完整版本(每个分类目录都是独立仓库,都含 repodata/):

[Server]
name=Server
baseurl=file:///yum/Server
enabled=1
gpgcheck=0

[HighAvailability]
name=HighAvailability
baseurl=file:///yum/HighAvailability
enabled=1
gpgcheck=0

[LoadBalancer]
name=LoadBalancer
baseurl=file:///yum/LoadBalancer/
enabled=1
gpgcheck=0

[ResilientStorage]
name=ResilientStorage
baseurl=file:///yum/ResilientStorage/
enabled=1
gpgcheck=0

[ScalableFileSystem]
name=ScalableFileSystem
baseurl=file:///yum/ScalableFileSystem
enabled=1
gpgcheck=0

CentOS 7 的 ISO 只有一个 Packages/ 目录和根目录下的 repodata/,不再有 HighAvailability 等分类目录,因此一个 [repodata] 段即可。

6.3 FTP / HTTP 网络源搭建

把一台机器的光盘内容共享出去,供内网其他机器使用。

HTTP 方式(httpd):

# 服务端
yum install -y httpd
systemctl enable --now httpd            # CentOS 7
# CentOS 6:chkconfig httpd on; service httpd start

mkdir -p /var/www/html/centos7
mount -o loop /root/CentOS-7-x86_64-DVD.iso /var/www/html/centos7
# 放行防火墙
firewall-cmd --permanent --add-service=http && firewall-cmd --reload   # CentOS 7
# CentOS 6:iptables -I INPUT -p tcp --dport 80 -j ACCEPT; service iptables save
setenforce 0        # 或配置正确的 SELinux 上下文

客户端 repo:

[http-base]
name=http base
baseurl=http://192.168.1.10/centos7/
enabled=1
gpgcheck=0

FTP 方式(vsftpd):

# 服务端
yum install -y vsftpd
systemctl enable --now vsftpd            # CentOS 7
# CentOS 6:chkconfig vsftpd on; service vsftpd start

mkdir -p /var/ftp/pub/centos7
mount -o loop /root/CentOS-7-x86_64-DVD.iso /var/ftp/pub/centos7
firewall-cmd --permanent --add-service=ftp && firewall-cmd --reload

客户端 repo:

[ftp-base]
name=ftp base
baseurl=ftp://192.168.1.10/pub/centos7/
enabled=1
gpgcheck=0

FTP/HTTP 服务本身的详细配置详见 阶段09 基础网络服务部署。

6.4 阿里云 / 网易镜像源配置

CentOS 7(备份原文件后直接下载现成 repo):

# 1. 备份
mkdir -p /etc/yum.repos.d/back_repo
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/back_repo/

# 2. 阿里云源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 或
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 3. 网易 163 源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo

# 4. 重建缓存
yum clean all
yum makecache
yum repolist

CentOS 6:

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS6-Base-163.repo
yum clean all && yum makecache

用 sed 直接改现有 repo 的地址(适用于 CentOS 7 EOL 后):

# 注释 mirrorlist,启用 baseurl,并把域名换成阿里云
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' \
           -e 's|^#baseurl=http://mirror.centos.org|baseurl=http://mirrors.aliyun.com|g' \
           /etc/yum.repos.d/CentOS-*.repo
yum clean all && yum makecache

注意:CentOS 7 已于 2024-06-30 结束生命周期(EOL),官方镜像不再提供更新,基于 mirrorlist 的 yum 源已无法解析,仓库内容迁移至 vault.centos.org。如需继续使用,需将 repo 文件改为直接指定 baseurl=http://vault.centos.org/...,或改用本地 ISO 源。

# 指向 vault 归档站点
sed -i -e 's|^mirrorlist=|#mirrorlist=|g' \
       -e 's|^#\?baseurl=http://mirror.centos.org/centos/\$releasever|baseurl=http://vault.centos.org/7.9.2009|g' \
       /etc/yum.repos.d/CentOS-*.repo

EPEL 源

EPEL(Extra Packages for Enterprise Linux)提供官方源之外的大量软件包。例如挂载 NTFS 分区需要的 ntfs-3g 位于 EPEL 源:

# 方式一:直接下载阿里云维护的 epel repo(推荐,国内速度快)
sudo wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sudo yum install ntfs-3g

# 方式二:安装 epel-release 包
yum install -y epel-release          # CentOS 7
yum install -y epel-release          # CentOS 6(部分镜像需手动装 rpm)
rpm -ivh https://archives.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm

# 临时只从 epel 安装
yum --enablerepo=epel install -y htop

常用软件安装与 yum 源配置的补充实操详见 05-02-常用软件安装与yum源配置.md

6.5 createrepo 制作本地私有仓库

若有一批第三方 RPM 包希望用 YUM 管理:

# 1. 准备目录,放入所有 RPM(及其依赖)
mkdir /myrepo
cp *.rpm /myrepo/

# 2. 安装 createrepo 工具
yum install -y createrepo

# 3. 生成 repodata 元数据
createrepo /myrepo/
# 常用选项
createrepo -v /myrepo/               # 显示详细过程
createrepo -d /myrepo/               # 生成 sqlite 数据库(加速)
createrepo -g comps.xml /myrepo/     # 同时生成软件组信息
createrepo --update /myrepo/         # 增量更新(新增 rpm 后只更新变化部分,快)

# 4. 在 /etc/yum.repos.d/localyum.repo 中新增仓库段
cat >> /etc/yum.repos.d/localyum.repo << EOF
[myrepo]
name=myrepo
baseurl=file:///myrepo/
enabled=1
gpgcheck=0
EOF

# 5. 刷新
yum clean all
yum makecache
yum repolist

后续每次往 /myrepo/ 增删 rpm 包,都必须重新执行 createrepo --update /myrepo/ 并 yum clean all,否则元数据与实际包不一致。

把私有仓库通过 httpd 发布给内网:

mv /myrepo /var/www/html/myrepo
createrepo --update /var/www/html/myrepo
# 客户端 baseurl=http://192.168.1.10/myrepo/

6.6 yum 源优先级:yum-plugin-priorities

多个仓库同时提供同名包时(如 base 与 epel 都有 nginx),需要控制优先使用哪个仓库。

# CentOS 6/7 需安装插件
yum install -y yum-plugin-priorities

# 确认插件已启用
cat /etc/yum/pluginconf.d/priorities.conf
# [main]
# enabled=1

# 确认 /etc/yum.conf 中 plugins=1
grep plugins /etc/yum.conf

在各 repo 段中加入 priority(1~99,数字越小优先级越高):

[base]
name=CentOS-$releasever - Base
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
enabled=1
gpgcheck=1
priority=1

[epel]
name=Extra Packages for Enterprise Linux
baseurl=http://mirrors.aliyun.com/epel/$releasever/$basearch/
enabled=1
gpgcheck=0
priority=10
# 验证:查看某个包来自哪个仓库
yum list nginx
yum info nginx | grep -i repo
yum --showduplicates list nginx      # 列出所有版本及来源仓库

配套手段:

  • exclude= 在低优先级仓库中排除特定包,如 epel 段加 exclude=nginx*。
  • cost=:不需插件,默认 1000,值小者优先,用于同优先级下的取舍。
  • CentOS 8+ 的 dnf 内置 priority 支持,无需安装插件。

6.7 离线环境同步仓库

方式一:yumdownloader 下载指定包及依赖

yum install -y yum-utils
mkdir /offline
yumdownloader --resolve --destdir=/offline nginx mariadb-server
createrepo /offline
# 拷到离线机器,配置 baseurl=file:///offline/

方式二:reposync 同步整个仓库(体积大,几十 GB)

# 查看仓库 ID
yum repolist

# 同步(-n 只同步最新版本,-p 指定输出目录,--download-metadata 同时拉元数据)
reposync -r base -p /data/repos -n --download-metadata
reposync -r updates -p /data/repos -n
reposync -r extras -p /data/repos -n
reposync -r epel -p /data/repos -n

# 若未同步元数据,需自行生成
createrepo /data/repos/base

# CentOS 8+
dnf reposync --repoid=baseos -p /data/repos --download-metadata

方式三:keepcache 复用已下载的包

# 修改 /etc/yum.conf
sed -i 's/^keepcache=0/keepcache=1/' /etc/yum.conf
# 之后所有 yum 安装的 rpm 都会保留在 /var/cache/yum/ 下
find /var/cache/yum -name '*.rpm' -exec cp {} /offline/ \;
createrepo /offline

方式四:只下载不安装

# CentOS 6 需插件
yum install -y yum-plugin-downloadonly
yum install --downloadonly --downloaddir=/offline nginx
# CentOS 7 内置该功能
yum install --downloadonly --downloaddir=/offline nginx
# CentOS 8+
dnf install --downloadonly --downloaddir=/offline nginx

七、源码编译安装

大部分源码包使用 autoconf 自动生成编译环境。源码包本身就是压缩包,安装前必须先解压并进入解压后的目录。

7.1 准备:依赖开发包与 Development Tools 组

编译需要编译器、make、头文件等基础工具,务必先装齐:

# 安装开发工具组(gcc、gcc-c++、make、autoconf、automake、libtool、patch 等)
yum groupinstall -y "Development Tools"
yum groupinstall -y "Development tools"        # 组名大小写不敏感
yum group install -y development              # CentOS 7 用组 ID
LANG=en_US.UTF-8 yum grouplist                # 中文环境下获取稳定的英文组名

# 单独安装最常用的几个
yum install -y gcc gcc-c++ make cmake autoconf automake libtool

# 常见的 -devel 开发包(提供头文件 .h 与静态库)
yum install -y zlib-devel openssl-devel pcre-devel \
               libxml2-devel libxslt-devel \
               ncurses-devel readline-devel \
               bzip2-devel xz-devel libffi-devel

关键概念:-devel 包提供编译期需要的头文件与链接符号。运行时只需主包(如 openssl-libs),但编译时必须装 openssl-devel。configure 报「找不到 xxx.h」几乎都是缺对应 -devel 包。

查找某个头文件属于哪个包:

yum provides '*/zlib.h'
yum whatprovides '*/pcre.h'
repoquery -l zlib-devel | grep '\.h$'

7.2 编译三部曲

# 1. 解压并进入目录
tar -xf wget-1.14.tar.xz
cd wget-1.14

# 目录中的 INSTALL / README 是安装帮助文档,务必先看
less README
less INSTALL
./configure --help          # 查看该软件支持的所有配置选项

# 2. 清理上一次编译残留(可选,非首次编译时用)
make clean
make distclean

# 3. 探测系统环境、检查依赖、配置功能
./configure
# 必须没有任何错误才能进入下一步;错误一般是依赖的工具或库没有安装、版本不对

# 4. 编译
make
sudo make -j4               # -j4 表示使用 4 个核心并行编译
make -j$(nproc)             # 用全部核心

# 5. 安装
sudo make install

# 6. 卸载
sudo make uninstall

各阶段做了什么:

阶段 做的事 产物
./configure 检测操作系统、CPU 架构、编译器、依赖库与头文件是否存在;根据传入参数决定启用哪些功能、装到哪里;把结果写入模板 Makefile、config.h、config.log、config.status
make 读取 Makefile,调用 gcc 把 .c/.cpp 编译为 .o,再链接成可执行文件与库。耗时取决于软件大小和机器性能 可执行文件、.so/.a 库(仍在源码目录内)
make install 把编译好的二进制、库、头文件、man 手册、配置文件按 --prefix 复制到目标目录 安装到 /usr/local/... 或自定义前缀

configure 报错时看 config.log 末尾,里面有 gcc 的原始报错,比屏幕输出更具体。

7.3 configure 常用参数

参数 作用
--help 列出该软件所有可用选项(最重要,每个软件都不同)
--prefix=/usr/local/nginx 指定安装根目录,最常用。二进制在 prefix/bin,库在 prefix/lib,配置在 prefix/etc
--exec-prefix=路径 单独指定与架构相关文件(可执行、库)的前缀
--bindir= / --sbindir= / --libdir= / --sysconfdir= / --includedir= / --mandir= 分别精确指定各类文件的安装目录
--with-xxx[=路径] 启用/链接某个外部依赖,如 --with-openssl=/usr/local/openssl、--with-http_ssl_module
--without-xxx 明确不使用某个外部依赖,如 --without-mysql
--enable-xxx 启用软件自带的某项可选功能,如 --enable-shared、--enable-threads
--disable-xxx 关闭某项默认开启的功能,用于绕过缺失依赖,如 --disable-gucharmap、--disable-assembly
--enable-static / --enable-shared 编译静态库 / 动态库
--build= / --host= / --target= 交叉编译三元组
CFLAGS= / CXXFLAGS= / LDFLAGS= / CPPFLAGS= 以环境变量形式传入编译/链接参数

示例:

# 指定安装路径 + 启用 SSL 与状态模块
./configure --prefix=/usr/local/nginx \
            --with-http_ssl_module \
            --with-http_stub_status_module \
            --with-pcre

# 用 -I/-L 指定非标准路径的头文件与库
./configure --prefix=/usr/local/myapp \
            CPPFLAGS=-I/usr/local/openssl/include \
            LDFLAGS=-L/usr/local/openssl/lib

# 关闭版本不匹配的可选功能(stardict 实例)
yum install -y gcc
./configure --disable-gucharmap --disable-festival

--with/--enable 的区别记忆:--with 面向「外部依赖」,--enable 面向「软件自身功能开关」。

强烈建议每次源码安装都显式指定 --prefix 到独立目录(如 /usr/local/软件名-版本号),既便于卸载,也便于多版本共存。

7.4 make clean / make distclean 与卸载

make clean       # 删除编译产生的 .o 和可执行文件,保留 Makefile 与 configure 结果
make distclean   # 更彻底:连 Makefile、config.h、config.status、config.log 一并删除,回到刚解压的状态

修改了 ./configure 参数需要重新配置时,应先 make distclean 再重新 ./configure,否则可能沿用旧配置导致诡异错误。

源码包的卸载有三种途径:

# 方式一:源码目录中执行(部分源码包支持,需保留源码目录与 Makefile)
sudo make uninstall

# 方式二:直接删除 --prefix 指定的安装目录(因此 prefix 必须独立)
rm -rf /usr/local/nginx
rm -f /etc/profile.d/nginx.sh /usr/local/bin/nginx
rm -f /usr/lib/systemd/system/nginx.service && systemctl daemon-reload

# 方式三:安装时用 checkinstall 生成 rpm 包,之后用 rpm -e 卸载(推荐)
yum install -y checkinstall
./configure --prefix=/usr/local/myapp
make
checkinstall -R --pkgname=myapp --pkgversion=1.0 make install
rpm -e myapp

若既不支持 make uninstall 又忘了 prefix,可通过安装前后的文件系统快照比对来定位:

find /usr/local -newer /tmp/timestamp        # 安装前先 touch /tmp/timestamp

7.5 库文件与 ldconfig

源码包安装的库默认放在 --prefix/lib,通常是 /usr/local/lib。系统默认只在以下目录查找动态库:

  • /lib/、/lib64/
  • /usr/lib/、/usr/lib64/

其他程序要使用该库,需把库路径加入系统配置:

# 查看一个程序依赖哪些库(类似 Windows 的 .dll)
ldd /bin/ls
ldd /usr/local/nginx/sbin/nginx      # 有 "not found" 说明缺库

# 新建配置文件(推荐方式,一个软件一个文件)
echo "/usr/local/lib" > /etc/ld.so.conf.d/fuse.conf

# 或直接追加到主配置
echo "/usr/local/lib" >> /etc/ld.so.conf

# 刷新动态库缓存
ldconfig
ldconfig -v                          # 显示处理过程
ldconfig -p | grep libfuse           # 查询缓存中是否已收录

# 临时生效(仅当前 shell)
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

fuse 的 README 中提示:

You may also need to add '/usr/local/lib' to '/etc/ld.so.conf' and/or run ldconfig.

系统标准库路径为 /usr/lib、/lib(64 位系统还有 /usr/lib64、/lib64)。

7.6 把源码安装的程序纳入 PATH 与 systemd 管理

用 --prefix=/usr/local/nginx 安装后,可执行文件在 /usr/local/nginx/sbin/nginx,不在 PATH 中,直接敲命令会 command not found。三种解决办法:

方法一:在 /etc/profile.d/ 下建脚本(推荐,对所有用户生效)

cat > /etc/profile.d/nginx.sh << 'EOF'
export NGINX_HOME=/usr/local/nginx
export PATH=$NGINX_HOME/sbin:$PATH
EOF
chmod 644 /etc/profile.d/nginx.sh
source /etc/profile.d/nginx.sh
which nginx

方法二:软链接到已在 PATH 中的目录

ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
ln -s /usr/local/mysql/bin/* /usr/bin/
hash -r        # 刷新 shell 的命令路径缓存
which nginx

方法三:只对当前用户生效

echo 'export PATH=/usr/local/nginx/sbin:$PATH' >> ~/.bash_profile
source ~/.bash_profile

顺带把 man 手册和头文件也纳入:

echo 'export MANPATH=/usr/local/nginx/share/man:$MANPATH' >> /etc/profile.d/nginx.sh
echo "/usr/local/nginx/lib" > /etc/ld.so.conf.d/nginx.conf && ldconfig

纳入 systemd 管理(CentOS 7+):

cat > /usr/lib/systemd/system/nginx.service << 'EOF'
[Unit]
Description=nginx - high performance web server
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now nginx
systemctl status nginx

CentOS 6(SysV init)对应做法:

# 把源码包自带的启动脚本放到 /etc/init.d/ 并注册
cp contrib/nginx.init /etc/init.d/nginx
chmod +x /etc/init.d/nginx
chkconfig --add nginx
chkconfig nginx on
service nginx start
# 或最简方式:写入 /etc/rc.local
echo "/usr/local/nginx/sbin/nginx" >> /etc/rc.local

systemd 与 init 脚本的完整语法详见 08-01-系统启动与服务管理.md

7.7 源码编译实例

实例一:编译安装 ntfs-3g(让 Linux 支持 NTFS)

Linux 内核本身支持 NTFS,但 RHEL 默认未编译该功能。生产环境很少需要,但学习场景下常用 NTFS 移动硬盘与 Linux 交换数据。

fuse(Filesystem in Userspace)是用户态文件系统模块:

# 解压源码
tar xf fuse-2.7.1.tar.gz -C /usr/src/
cd /usr/src/fuse-2.7.1/

# 经典三步
./configure
make
make install

# 加载模块(RHEL 6.3 已自带 fuse 模块,可能无需此步)
modprobe fuse

ntfs-3g:

tar xf ntfs-3g_ntfsprogs-2014.2.15.tgz -C /usr/src/
cd /usr/src/ntfs-3g_ntfsprogs-2014.2.15/
./configure
make
make install

# 验证:出现此命令说明安装成功
which mount.ntfs-3g
# /sbin/mount.ntfs-3g

# 挂载 NTFS 分区
mount.ntfs-3g /dev/sdb1 /mnt

另一份源码为 ntfs-3g-2009.4.4.tgz,编译安装后同样使用 mount.ntfs-3g 挂载 NTFS 分区。CentOS 7 下可直接从 EPEL 源 yum install ntfs-3g,无需编译。

实例二:MPlayer

源码 MPlayer-1.2.tar.xz,依赖 yasm(需先编译或 yum install yasm)。

实例三:星际译王 stardict 3.0.2

sudo yum install gcc -y
./configure --disable-gucharmap --disable-festival

常见依赖:intltool、gnome-doc-utils、enchant-devel、espeak-devel、libgnomeui-devel、gcc-c++、scrollkeeper 等,按报错逐一 yum install;gucharmap-devel、festival-devel 版本不匹配时通过 --disable-gucharmap、--disable-festival 跳过。源码中 scene.hpp 第 21 行附近若使用 NULL 编译失败,可将 NULL 改为 0。

实例四:坦克大战 tank-sdl

662206tank-sdl-0.3.0.tar.gz,安装 libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev(CentOS 中对应包名类似 SDL*_devel)。

实例五:仙剑奇侠传 sdlpal

进入 sdlpal/code,make clean && make;如链接报错可编辑 nbproject/Makefile-Release.mk,加上 LDLIBSOPTIONS=-lm -lSDL,再把可执行文件复制出来运行:

cp dist/Release/GNU-Linux-x86/sdlpal ..
cd ..
./sdlpal

实例六:终端打字程序 ptyping

源码包 ptyping-1.0.1.tar.gz,标准三部曲即可。

编译 SDL-1.2 常见错误

错误:operand type mismatch for `movq'
解决:./configure --disable-assembly

错误:./src/video/x11/SDL_x11sym.h:168:17: error: conflicting types for '_XData32'
解决:vim ./src/video/x11/SDL_x11sym.h +168
      修改 SDL_X11_SYM(int,_XData32,(Display *dpy,register _Xconst long *data,unsigned len),(dpy,data,len),return)

错误:undefined reference to `_XGetRequest'
解决:vim Makefile +171
      LIBS = -L/kyo/code/lib -Wl,-rpath,/kyo/code/lib -lSDL -lpthread -lX11

7.8 源码安装与包管理器安装的优劣对比

对比项 包管理器安装(rpm/yum) 源码编译安装
安装速度 快,秒级 慢,大型软件可达数十分钟至数小时
依赖处理 yum 自动解决 全部手动安装 -devel 包
功能定制 不可改,由打包者决定 可自由开关模块、打补丁、指定优化参数
版本选择 受仓库限制,往往偏旧 可用最新版(甚至开发版)
安装路径 固定标准路径(/usr/bin、/etc) 由 --prefix 任意指定,可多版本共存
卸载 rpm -e / yum remove,干净彻底 依赖 make uninstall 或手动删目录,易残留
升级 yum update 一条命令 重新下载、重新编译、重新安装
安全更新 发行版统一推送补丁 需自己跟踪上游 CVE
文件校验 rpm -V 可校验完整性 无校验机制
统一管理 可查询、可审计(rpm -qa、yum history) 不在包数据库中,rpm -qf 查不到
服务集成 自带 systemd unit / init 脚本、日志轮转配置 需手写 unit 文件、logrotate 配置
适用场景 绝大多数生产环境、批量部署 需特定版本/特定编译参数/性能调优的场景

结论:生产环境优先使用系统包管理器安装软件,便于后续维护和升级;只有在需要特定版本或定制功能时才源码编译,并做好安装路径、依赖、卸载方式的文档记录。

混用风险:同一软件既 yum 装过又源码装过,会出现两个版本共存、which 指向不确定、配置文件互相干扰的问题。源码安装前先确认 rpm -qa | grep 软件名 是否已装并卸载干净。

内核编译属于特殊的源码编译场景,详见 05-03-内核编译与系统启动过程.md


八、排错清单

8.1 依赖冲突与依赖缺失

现象一:rpm -ivh 报 Failed dependencies

error: Failed dependencies:
        libibverbs.so.1()(64bit) is needed by scsi-target-utils-...
        perl(Config::General) is needed by scsi-target-utils-...

定位与解决:

# 1. 查清缺的东西由谁提供
yum provides 'libibverbs.so.1()(64bit)'
yum whatprovides 'perl(Config::General)'
rpm -qpR 包文件.rpm                 # 先看清这个包要什么

# 2. 首选:改用 yum 安装本地 rpm,让 yum 自动补依赖
yum install ./scsi-target-utils-xxx.rpm      # CentOS 7
yum localinstall ./scsi-target-utils-xxx.rpm # CentOS 6

# 3. 循环依赖:同一条命令一起装
rpm -ivh xfig-*.rpm xfig-common-*.rpm

# 4. 最后手段(高风险):忽略依赖
rpm -ivh --nodeps 包.rpm

现象二:yum update 报 Protected multilib versions / Transaction check error / 包冲突

yum --skip-broken update                  # 跳过有问题的包继续
yum clean all && yum makecache
package-cleanup --problems                # 列出所有依赖问题
package-cleanup --dupes                   # 找出重复安装的包
package-cleanup --cleandupes              # 清理重复包
yum check                                 # 检查 rpm 数据库依赖一致性
yum distro-sync                            # 把所有包同步到仓库版本,解决版本错乱
rpm -e --nodeps 冲突的旧包                 # 精确移除冲突方后重试
yum install 包名-版本-发布号               # 指定版本安装避开冲突
yum --showduplicates list 包名             # 查看仓库中有哪些版本可选

现象三:多仓库同名包版本打架

# 装 yum-plugin-priorities 并给 base 设 priority=1、epel 设 priority=10
# 或在低优先级仓库中 exclude
yum --disablerepo=epel install 包名

8.2 yum 源不可用

现象:Cannot find a valid baseurl for repo: base/7/x86_64、Could not resolve host: mirrorlist.centos.org、[Errno 14] curl#6 - "Could not resolve host"

排查顺序:

# 1. 网络与 DNS
ping -c2 223.5.5.5
ping -c2 mirrors.aliyun.com
cat /etc/resolv.conf                    # 确认有可用 nameserver
nslookup mirrors.aliyun.com

# 2. 网卡是否启用(CentOS 7 常见:ONBOOT=no)
nmcli connection show
grep ONBOOT /etc/sysconfig/network-scripts/ifcfg-*
# 改成 ONBOOT=yes 后重启网络
systemctl restart network               # CentOS 7
service network restart                 # CentOS 6

# 3. 检查仓库配置
yum repolist all
cat /etc/yum.repos.d/*.repo
ls -l /etc/yum.repos.d/                 # 文件名是否以 .repo 结尾

# 4. CentOS 7 EOL 后 mirrorlist 已失效:改用 vault 或阿里云 baseurl
# 5. 需要代理的环境
echo 'proxy=http://10.0.0.1:8080' >> /etc/yum.conf
# 6. 清缓存重建
yum clean all && rm -rf /var/cache/yum/* && yum makecache

现象:file:///yun/repodata/repomd.xml: [Errno 14] Could not open/read file:///yun/repodata/repomd.xml

表示 baseurl 路径下找不到软件仓库。检查:

  • 路径是否拼写正确(上例把 /yum 写成了 /yun);
  • ISO 是否已正确挂载到该目录:mount | grep yum、ls /yum/repodata/repomd.xml;
  • baseurl 是否指到了 Packages/ 目录(错误),应指向包含 repodata/ 的上一级目录;
  • 自建仓库是否忘了执行 createrepo。
mount | grep /yum
ls /yum/repodata/
mount -o loop /root/centos.iso /yum     # 重新挂载
createrepo /myrepo/                     # 自建仓库补元数据

现象:当前目录存在通配符同名文件导致 No package perlaaa available / Error: Nothing to do

当前目录下若有一个名为 perlaaa 的文件,执行 yum install perl* 时 shell 会先把 perl* 展开为本地文件名,导致 YUM 报错。

解决:切换到不含匹配文件的目录再执行,或用引号包裹包名:

yum install 'perl*'
yum install "perl*"

8.3 GPG 校验失败

现象:

warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
Public key for vsftpd-...rpm is not installed
GPG key retrieval failed: [Errno 14] Could not open/read file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Package xxx.rpm is not signed

解决办法(按推荐顺序):

# 1. 导入正确的公钥(最推荐)
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7          # CentOS 7
rpm --import /yum/RPM-GPG-KEY-redhat-release                # RHEL 6 光盘根目录
cd /yum/ && rpm --import RPM-GPG-KEY-redhat-release
rpm --import http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

# 2. 确认公钥已导入
rpm -qa | grep pubkey
rpm -qi gpg-pubkey-f4a80eb5-53a7ff4b

# 3. 检查 repo 中 gpgkey 路径是否存在
grep -A1 gpgkey /etc/yum.repos.d/*.repo
ls -l /etc/pki/rpm-gpg/

# 4. 临时跳过校验
yum install --nogpgcheck 包名
rpm -ivh --nosignature 包.rpm

# 5. 永久关闭该仓库校验(把 gpgcheck=1 改为 gpgcheck=0)
sed -i 's/^gpgcheck=1/gpgcheck=0/' /etc/yum.repos.d/localyum.repo

# 6. 手动验证某个包的签名
rpm --checksig 包.rpm
rpm -K 包.rpm

# 7. 公钥过期/更换:先删旧公钥再导入新的
rpm -e gpg-pubkey-旧ID

用 rpm -ivh 安装时 NOKEY 只是 warning,不影响安装;用 yum 且 gpgcheck=1 时会直接失败。

8.4 rpm 数据库损坏

现象:rpm -qa 卡住无输出、error: rpmdb: BDB0113 Thread died in Berkeley DB library、error: cannot open Packages database in /var/lib/rpm、error: db5 error(-30973) from dbenv->failchk

# 1. 备份(必做)
cp -a /var/lib/rpm /var/lib/rpm.bak-$(date +%F)

# 2. 确认没有 rpm/yum 进程在跑
ps -ef | grep -E 'yum|rpm' | grep -v grep

# 3. 删除锁与共享内存文件
rm -f /var/lib/rpm/__db.*

# 4. 重建数据库
rpm --rebuilddb
rpm -vv --rebuilddb          # 显示详细过程

# 5. 验证
rpm -qa | wc -l

# 6. 仍失败时用 Berkeley DB 工具修复
yum install -y db4-utils      # CentOS 6
yum install -y libdb-utils    # CentOS 7
db_verify /var/lib/rpm/Packages
cd /var/lib/rpm && /usr/lib/rpm/rpmdb_recover
rm -f __db.* && rpm --rebuilddb

# 7. 清 yum 缓存后测试
yum clean all && yum makecache

重建期间不要中断,也不要同时运行 yum。若 Packages 文件彻底损坏且无备份,只能从同版本系统复制或重装。

8.5 yum 进程被锁

现象:

Another app is currently holding the yum lock; waiting for it to exit...
The other application is: yum
State  : Sleeping, pid: 14824
Existing lock /var/run/yum.pid: another copy is running as pid 14824.

YUM 不允许并发执行。处理:

# 1. 查清是谁持有锁
cat /var/run/yum.pid
ps -ef | grep yum
ps aux | grep 14824

# 2. 若是 PackageKit/yum-cron 等后台自动更新,等待其结束,或关闭它
systemctl stop packagekit                 # CentOS 7
systemctl disable --now yum-cron
service yum-updatesd stop                 # CentOS 6

# 3. 确认进程确实已死后,再删除锁文件(顺序不能颠倒)
kill -9 14824
rm -f /var/run/yum.pid
# CentOS 6 部分版本锁文件在 /var/run/yum.pid,事务锁在 /var/lib/rpm/.rpm.lock

# 4. 重试
yum clean all && yum makecache

严禁在 yum 正在写 rpm 数据库时强杀,容易造成 8.4 的数据库损坏。若已强杀,先做 rpm --rebuilddb。

8.6 编译报错:缺头文件的定位方法

现象:

fatal error: zlib.h: No such file or directory
configure: error: pcre.h not found
error: Python.h: 没有那个文件或目录

定位五步法:

# 1. 先看 config.log 末尾的原始 gcc 报错,比屏幕输出精确
tail -50 config.log
grep -n 'error' config.log | tail -20

# 2. 记下缺失的头文件名,反查提供它的包
yum provides '*/zlib.h'
yum whatprovides '*/pcre.h'
yum provides '*/Python.h'
# 结果通常是 xxx-devel 包

# 3. 安装对应 -devel 包
yum install -y zlib-devel pcre-devel python-devel

# 4. 若头文件在非标准路径(自行编译的依赖),用 -I 告知
./configure CPPFLAGS=-I/usr/local/openssl/include
gcc -I/kyo/code/include ...
# Makefile 中:CFLAGS=-I/kyo/code/include

# 5. 确认头文件确实存在
find / -name 'zlib.h' 2>/dev/null
rpm -ql zlib-devel | grep '\.h$'
问题 解决思路 具体做法
找不到 *.h 头文件 用 -I 指定头文件路径 gcc -I/kyo/code/include;Makefile 中通过 CFLAGS=-I/kyo/code/include 指定;或安装对应 -devel 包
undefined reference to '_XGetRequest'(链接期缺库) 用 -l 指定链接库 Makefile 中通过 LDFLAGS=-lX11 或 LIBS=-lX11 指定
ld: 找不到 -lSDL 用 -L 指定库搜索路径 Makefile 中 LDFLAGS=-L/kyo/code/lib -lSDL -lSDL_image -lSDL_mixer -lX11
运行时报 error while loading shared libraries: libXXX.so.x 让系统在运行时找到动态库 临时:export LD_LIBRARY_PATH=/kyo/code/lib;永久:把库路径追加到 /etc/ld.so.conf,再执行 sudo ldconfig

8.7 编译报错:缺库与 pkg-config

现象:/usr/bin/ld: cannot find -lssl、undefined reference to 'SSL_library_init'、No package 'glib-2.0' found

# 1. 反查库文件属于哪个包
yum provides '*/libssl.so'
yum provides '*/libz.so.1'
yum install -y openssl-devel

# 2. pkg-config 找不到 .pc 文件时,指定搜索路径
pkg-config --list-all | grep glib
pkg-config --cflags --libs glib-2.0
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/lib64/pkgconfig
find / -name '*.pc' 2>/dev/null | grep glib

# 3. 链接期指定库路径与库名(注意 -l 顺序在源文件之后)
gcc main.c -L/usr/local/lib -lssl -lcrypto -o main
./configure LDFLAGS='-L/usr/local/lib' LIBS='-lssl -lcrypto'

# 4. 只有 .so.1 没有 .so 时(缺 devel 的软链接),手动补
ln -s /usr/lib64/libssl.so.10 /usr/lib64/libssl.so
ldconfig

# 5. 64 位系统误装了 32 位库
rpm -qa | grep openssl
yum install -y openssl-devel.x86_64

8.8 make install 后找不到命令

# 1. 确认文件到底装到哪了
ls /usr/local/nginx/sbin/
grep -i prefix config.log | head
find / -name nginx -type f 2>/dev/null

# 2. 不在 PATH → 建 profile.d 脚本或软链接(见 7.6)
echo $PATH
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
hash -r          # 关键:清除 shell 命令缓存,否则仍报 command not found

# 3. 装了但一运行就报缺 .so
ldd /usr/local/nginx/sbin/nginx | grep 'not found'
echo "/usr/local/lib" > /etc/ld.so.conf.d/nginx.conf && ldconfig

# 4. sudo 下找不到命令(secure_path 不含自定义目录)
sudo env PATH=$PATH nginx -v
visudo    # 修改 Defaults secure_path 追加 /usr/local/nginx/sbin

# 5. rpm 装的命令找不到:确认包完整
rpm -V 包名
yum reinstall 包名 -y
rpm -ivh --force 包.rpm

九、附录:GPG 文件加密

旁支内容:GPG 是 rpm 包签名校验(gpgcheck/gpgkey)所依赖的加密工具,此处保留源文档原文;文件加密与系统安全的其他内容详见 阶段02 用户与权限。

GPG(GNU Privacy Guard,GNUPG)是开源的非对称加密工具,采用 RSA 算法,使用公钥加密、私钥解密。

9.1 安装与密钥管理

# CentOS 安装
sudo yum install gnupg -y
yum install gnupg -y

gpg --list-keys                 # 查看当前系统所有密钥对
gpg --list-secret-keys          # 只看私钥
gpg --gen-key                   # 创建密钥对(旧版)
gpg --full-generate-key         # 创建密钥对(新版,可选算法与长度)
操作 命令
查看所有密钥 gpg --list-keys
创建密钥对 gpg --full-generate-key(旧版使用 gpg --gen-key)
导出公钥 gpg -a -o public.key --export 密钥标识
导出私钥 gpg -a -o private.key --export-secret-keys 密钥标识
导入密钥 gpg --import 密钥文件
设置密钥信任 gpg --edit-key 密钥标识 trust quit
上传公钥 gpg --keyserver hkps://keyserver.ubuntu.com --send-keys 公钥ID
查找公钥 gpg --keyserver hkps://keyserver.ubuntu.com --search-keys 公钥标识

创建密钥对时按提示依次选择:

  1. 加密算法(推荐默认,直接回车);
  2. 密钥长度(默认 2048,可选 1024/2048/4096,越长越安全但生成越久);
  3. 密钥有效期(默认永不过期);
  4. 确认以上信息;
  5. 输入密钥信息(姓名、邮箱、注释);
  6. 输入密钥保护密码。

9.2 加密与解密

加密:

# 格式
gpg -r 密钥标识 [-o 加密输出文件] -e [待加密文件]

# 加密 /etc/passwd,生成文本格式(-a)的加密文件
gpg -r 1234567@163.com -o /tmp/test/gpg.file -a -e /etc/passwd

说明:

  • -r 指定密钥标识,即创建密钥时输入的真实姓名或邮箱;
  • 默认生成二进制格式,加 -a 生成文本格式(ASCII Armored);
  • 不指定 -o 时输出到标准输出;不指定待加密文件时从标准输入读取。

解密:

# 格式
gpg -r 密钥标识 [-o 解密输出文件] -d [加密文件]

# 解密(解密不需要指定 -r)
gpg -o /tmp/passwd -d /tmp/test/gpg.file

# 不指定 -o 时解密到标准输出,不指定加密文件时从标准输入读取

提示:-r 指定密钥标识(真实姓名或邮箱),-a 输出 ASCII 文本格式,-e 加密,-d 解密。

-r(--recipient)只在加密时有意义,用于指定用谁的公钥加密;解密时 gpg 会自动从加密文件头中读取所需的密钥 ID,再到本地钥匙环里找对应私钥,写 -r 不起作用。

9.3 公钥 / 私钥导入导出与信任

# 导出公钥
gpg -a -o public.key --export 1234567@163.com

# 导出私钥
gpg -a -o private.key --export-secret-keys 1234567@163.com

# 导入密钥(公钥或私钥)
gpg --import 密钥导出文件

导入私钥后,需要设置密钥信任,否则每次加密都会提示信任问题:

gpg --edit-key 1234567@163.com trust quit
# 选择 5(最高信任级别),再按 y 确认退出

9.4 公钥服务器

# 上传公钥
gpg --keyserver hkp://keys.gnupg.net --send-keys 公钥ID

# 查找公钥
gpg --keyserver hkp://keys.gnupg.net --search-keys 公钥标识

# 推荐使用的新服务器
gpg --keyserver hkps://keys.openpgp.org --send-keys 公钥ID
gpg --keyserver hkps://keyserver.ubuntu.com --search-keys 公钥标识

密钥服务器方面,旧文档常见的 hkp://keys.gnupg.net 随 SKS 网络在 2019 年前后瓦解已停止服务,请改用 hkps://keys.openpgp.org 或 hkps://keyserver.ubuntu.com。

使用 GPG 加密时务必妥善保管私钥,公钥可分发供他人加密文件给你。


十、练习

练习 1:tar 打包与解包(源文档原题)

题目:

  1. 在 ~/uplooking/7_software/tmp/ 下创建 file{1..10}(大小 100M)和目录 dir{1..10},每个目录中创建 file{1..10}(大小 200M)。
  2. 把该目录下所有文件和文件夹打包为 1_tar.tar。
  3. 查看压缩包内容与压缩包大小。
  4. 把压缩包内容解压到当前目录。
  5. 把压缩包内容解压到父目录。
  6. 删除解压出来的内容。

参考答案:

# 1. 批量创建测试文件与目录(嵌套花括号展开)
mkdir -p ~/uplooking/7_software/tmp/{file{1..10},dir{1..10}}
cd ~/uplooking/7_software/tmp/

# 造 100M 的大文件,便于观察打包压缩效果
dd if=/dev/zero of=~/uplooking/7_software/tmp/file1 bs=100M count=1
for i in {1..10}; do dd if=/dev/zero of=file$i bs=100M count=1; done
for d in dir{1..10}; do for i in {1..10}; do dd if=/dev/zero of=$d/file$i bs=200M count=1; done; done

# 2. 打包
tar -cf 1_tar.tar ~/uplooking/7_software/tmp/
tar -cvf 1_tar.tar ./

# 3. 查看包内容与包大小
tar -tf 1_tar.tar
tar -tvf 1_tar.tar
ls -lh 1_tar.tar
du -sh 1_tar.tar

# 4. 解包到当前目录
tar -xf 1_tar.tar

# 5. 解包到上一级(父)目录
tar -xf 1_tar.tar -C ../

# 6. 删除解压出来的内容
rm -rf ../home ../root ../uplooking

说明:{file{1..10},dir{1..10}} 是嵌套花括号展开,一条命令即可创建 20 个条目;dd if=/dev/zero of=文件 bs=100M count=1 从 /dev/zero 读取数据生成指定大小的空文件,bs 为每次读写的块大小,count 为块数。

练习 2:gzip 压缩与解压(源文档原题)

题目:

  1. 创建一个目录,在目录中创建多个普通文件。
  2. 使用命令将目录中的所有普通文件进行压缩。
  3. 使用命令将刚刚压缩后的文件进行解压。

参考答案:

mkdir /test
cd /test
touch {1..10}.txt

# 压缩(两种写法)
gzip -r /test/*
cd /test && gzip *

# 解压
gzip -dr /test/*
gzip -d *.gz
gunzip *.gz

练习 3:tar 调用 gzip 压缩与指定目录解压(源文档原题)

题目:

  1. 创建一个 test 目录,目录中创建多个子目录和普通文件。
  2. 使用 tar 命令将 test 目录进行打包压缩,要求打包压缩后的文件格式为 test.tar.gz(需要调用 gzip 压缩,即使用 -z 选项)。
  3. 使用命令将刚刚压缩好的文件解压出来,并放到指定目录 /test/bbb 中。

参考答案:

mkdir -p /test/{aaa,bbb,ccc}
touch /test/{1..5}.txt /test/aaa/{a,b,c}.txt

# 打包并调用 gzip 压缩
tar -czvf test.tar.gz /test
tar -czvf test.tar.gz test        # 相对路径写法(推荐)

# 解压到指定目录(-C 放在归档文件后面)
mkdir -p /test/bbb
tar -xzvf test.tar.gz -C /test/bbb
ls -R /test/bbb

练习 4:rpm 查询练习(源文档原题)

题目:配合 RPM 查询命令速查表,用系统自带的 coreutils 包动手验证。

参考答案:

rpm -qa | grep coreutils        # 是否安装
rpm -qi coreutils               # 描述信息
rpm -ql coreutils               # 释放了哪些文件
rpm -qc coreutils               # 配置文件
rpm -qd coreutils               # 文档文件
rpm -qR coreutils               # 依赖
rpm -V coreutils                # 完整性校验
rpm -qf /bin/bash               # /bin/bash 属于哪个包 → bash
rpm -qf $(which wget)           # wget 命令属于哪个包

练习 5:卸载并恢复一个命令

题目:卸载 wget,确认命令消失,再用两种方式恢复它。

参考答案:

# 卸载
which wget                                    # /usr/bin/wget
rpm -qf /usr/bin/wget                         # wget-1.14-15.el7_4.1.x86_64
rpm -e wget-1.14-15.el7_4.1.x86_64
rpm -e $(rpm -qf $(which wget))               # 一步到位
wget --version                                # command not found

# 恢复方式一:yum
yum install -y wget

# 恢复方式二:光盘中的 rpm 文件
rpm -ivh /yum/Packages/wget-1.14-15.el7_4.1.x86_64.rpm

# 恢复方式三:只提取文件,不走包管理
rpm2cpio /yum/Packages/wget-1.14-*.rpm | cpio -idmv './usr/bin/wget'
cp ./usr/bin/wget /usr/bin/wget

练习 6:配置本地光盘 yum 源并离线验证

参考答案:

mkdir /yum
mount -o loop /root/CentOS-7-x86_64-DVD.iso /yum
mkdir -p /etc/yum.repos.d/back_repo
mv /etc/yum.repos.d/CentOS-* /etc/yum.repos.d/back_repo/
cat > /etc/yum.repos.d/local.repo << 'EOF'
[repodata]
name=repodata
baseurl=file:///yum/
enabled=1
gpgcheck=0
EOF
yum clean all && yum makecache && yum repolist
# 断网后测试
yum install -y vim
# 开机自动挂载
echo '/root/CentOS-7-x86_64-DVD.iso  /yum  iso9660  loop,defaults  0 0' >> /etc/fstab
mount -a

练习 7:用 createrepo 自建仓库

参考答案:

mkdir /myrepo
yumdownloader --resolve --destdir=/myrepo htop nginx
yum install -y createrepo
createrepo /myrepo/
cat >> /etc/yum.repos.d/localyum.repo << 'EOF'
[myrepo]
name=myrepo
baseurl=file:///myrepo/
enabled=1
gpgcheck=0
EOF
yum clean all && yum makecache
yum --disablerepo='*' --enablerepo=myrepo list available
# 新增 rpm 后必须更新元数据
cp new.rpm /myrepo/ && createrepo --update /myrepo/ && yum clean all

练习 8:yum 查询三连

题目:分别查出 (1) 提供 netstat 命令的包;(2) screen 包的依赖;(3) 仓库中 nginx 的所有可用版本及来源仓库。

参考答案:

yum provides '*/netstat'          # → net-tools
yum whatprovides '*bin/netstat'
yum deplist screen
yum --showduplicates list nginx
yum info nginx
repoquery -l nginx                # 未安装也能看包内文件

练习 9:源码编译安装 wget 到指定目录并纳入 PATH

参考答案:

yum groupinstall -y "Development Tools"
yum install -y openssl-devel
tar -xf wget-1.14.tar.xz
cd wget-1.14
./configure --help | less
./configure --prefix=/usr/local/wget-1.14 --with-ssl=openssl
make -j$(nproc)
make install
ls /usr/local/wget-1.14/bin/

# 纳入 PATH
cat > /etc/profile.d/wget.sh << 'EOF'
export PATH=/usr/local/wget-1.14/bin:$PATH
EOF
source /etc/profile.d/wget.sh
hash -r
which wget && wget --version

# 卸载
make uninstall           # 或
rm -rf /usr/local/wget-1.14 /etc/profile.d/wget.sh

练习 10:备份与分割综合题

题目:把 /etc 打包为带日期的 xz 压缩包,排除所有 .log 文件,切分为每片 20M,再在另一目录还原并校验。

参考答案:

# 打包(排除 log,xz 压缩,带日期)
tar -cJvf /backup/etc-$(date +%F).tar.xz /etc --exclude='*.log'

# 校验归档可读
tar -tJf /backup/etc-$(date +%F).tar.xz > /dev/null; if ($?) { echo OK }
md5sum /backup/etc-$(date +%F).tar.xz > /backup/etc.md5

# 分割
cd /backup
split -b 20M -d etc-$(date +%F).tar.xz etc.part

# 还原
mkdir -p /restore && cd /restore
cat /backup/etc.part* > etc.tar.xz
md5sum -c /backup/etc.md5      # 或手动比对
tar -xJf etc.tar.xz -C /restore
ls /restore/etc | head

练习 11:排错演练

题目:模拟并修复以下三种故障。

参考答案:

# (1) rpm 数据库损坏
cp -a /var/lib/rpm /var/lib/rpm.bak
rm -f /var/lib/rpm/__db.*
rpm --rebuilddb
rpm -qa | wc -l

# (2) yum 被锁
cat /var/run/yum.pid; ps -ef | grep yum
kill -9 $(cat /var/run/yum.pid); rm -f /var/run/yum.pid

# (3) 误删文件后修复(不重装整包)
rm -f /usr/bin/wget
rpm -V wget                       # 输出 missing /usr/bin/wget
yum reinstall -y wget             # CentOS 7
rpm -ivh --force wget-*.rpm       # CentOS 6

小结与注意事项

  • RPM 适合单包操作,但依赖关系需要人工解决;-ivh 安装、-Uvh 升级、-e 卸载、-qa/-q/-qi/-ql/-qc/-qd/-qf/-qR 查询、-V 校验、rpm2cpio 提取文件、rpm --rebuilddb 修数据库。
  • rpm 安装不自动处理依赖,适合本地单个包安装或查询;--nodeps 与 --force 属高风险选项,生产慎用。
  • src.rpm 是「带 spec 的源码包」,用 rpmbuild --ba 或 --rebuild 可在本机编译出适配的二进制 RPM。
  • YUM 是 RPM 的自动前端,核心是配置 /etc/yum.repos.d/*.repo,能自动解决依赖,还能通过包组、createrepo 自建仓库、priorities 插件扩展能力。
  • yum 安装前建议执行 yum clean all && yum makecache 确保缓存最新;改动 repo 文件或仓库内容后必须清缓存。
  • CentOS 6 用 yum + service/chkconfig/rc.local,CentOS 7 用 yum + systemd,CentOS 8+ 用 dnf + 模块化仓库,命令与配置路径的差异见第 5.6、6.2 节。
  • 压缩与归档:tar 负责归档,gzip/bzip2/xz 负责压缩;压缩率 xz > bzip2 > gzip,速度相反;-f 必须紧跟文件名,-C 放在归档文件之后。
  • 源码包通过 ./configure && make && make install 三步安装,适合需要定制功能的场景;配合 --prefix 和 ldconfig 管理路径与库文件。
  • 源码编译安装灵活,但需要手动解决依赖,且卸载依赖 make uninstall,建议记录安装路径。
  • 生产环境优先使用系统包管理器安装软件,便于后续维护和升级。
最后修改:2026 年 09 月 20 日
如果觉得我的文章对你有用,请随意赞赏