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-...
解决方法:
-
系统 ISO 中的包:依赖包一定在 ISO 中,需逐一找到并按顺序安装。
-
第三方包:依赖不保证齐全,需自行解决。
-
循环依赖:若 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 时,可以:
- 下载对应
.src.rpm,在本机编译生成适配当前平台的 RPM; - 或直接下载源码包手动编译安装(见下文源码编译章节)。
五、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 步骤:
-
预备目录并挂载 ISO:
mkdir /yum mount -o loop /soul/images/centos.iso /yum # 只读挂载写法 mount -ro loop centos.iso /yum # 若是物理光驱 mount /dev/cdrom /yum -
备份系统原有 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 -
清空缓存并验证:
yum clean all yum makecache yum list yum repolist # 测试:拔掉网线后执行 sudo yum install vim -y若提示「软件包已安装/最新」而非网络错误,说明本地源生效。
-
设置开机自动挂载 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 公钥标识 |
创建密钥对时按提示依次选择:
- 加密算法(推荐默认,直接回车);
- 密钥长度(默认 2048,可选 1024/2048/4096,越长越安全但生成越久);
- 密钥有效期(默认永不过期);
- 确认以上信息;
- 输入密钥信息(姓名、邮箱、注释);
- 输入密钥保护密码。
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 打包与解包(源文档原题)
题目:
- 在
~/uplooking/7_software/tmp/下创建file{1..10}(大小 100M)和目录dir{1..10},每个目录中创建file{1..10}(大小 200M)。 - 把该目录下所有文件和文件夹打包为
1_tar.tar。 - 查看压缩包内容与压缩包大小。
- 把压缩包内容解压到当前目录。
- 把压缩包内容解压到父目录。
- 删除解压出来的内容。
参考答案:
# 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 压缩与解压(源文档原题)
题目:
- 创建一个目录,在目录中创建多个普通文件。
- 使用命令将目录中的所有普通文件进行压缩。
- 使用命令将刚刚压缩后的文件进行解压。
参考答案:
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 压缩与指定目录解压(源文档原题)
题目:
- 创建一个
test目录,目录中创建多个子目录和普通文件。 - 使用
tar命令将test目录进行打包压缩,要求打包压缩后的文件格式为test.tar.gz(需要调用 gzip 压缩,即使用-z选项)。 - 使用命令将刚刚压缩好的文件解压出来,并放到指定目录
/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,建议记录安装路径。 - 生产环境优先使用系统包管理器安装软件,便于后续维护和升级。
此处评论已关闭