文章目录

  • rpm包命名规则
  • rpm数据库
  • 安装程序包
  • 升级
  • 卸载
  • 查询
    • select-options
    • query-options
  • 校验
  • 数字签名
    • 公钥
  • 数据库重建
  • 获取需要的程序包

centos上安装程序包的的通常都是直接使用yum命令,yum实际是以rpm为核心的一套前端包管理命令,所以学习centos的程序包管理需要从rpm开始。

yumrhel 系列系统上 rpm管理器的前端工具,在 centos6/7 上被广泛使用。centos8中,包管理器变成了dnfdnf基本可以认为是改良版的 zypper(S.u.S.E.rpm包管理器),yumcentos8中是dnf的符号连接,命令也和yum保持一致。

rpm 是 redhat package manager 的缩写,redhat 贡献出来的软件包管理工具,是linux红帽系包管理事实上的标准。它能够将源代码编译并打包成为符合rpm机制的程序包,在软件包里会有默认的清单列表,例如软件包加密的特征码、安装时需要依赖的其他程序包列表等。

这样在安装的时候,rpm就会使用特征码对软件包做来源和有效性验证,然后根据依赖列表来查看系统是否满足依赖要求等,如果一切顺利在安装完成后,将安装信息整个的写入rpm的数据库,已备未来查询、验证和卸载等操作。

来自《鸟哥linux私房菜》

为何说 CentOS 是『社群维护的企业版』呢? Red Hat 公司的 RHEL 释出后,连带会将 SRPM 释出。 社群的朋友就将这些 SRPM 收集起来幵重新编译成为所需要的软件,再重复释出成为 CentOS,所以才能号称不 Red Hat 的RHEL 企业版同步啊!真要感谢 SRPM 哩!如果妳想要理解 CentOS 是如何编译一支程序的, 也能够透过学习SRPM 内吨的编译参数,来学习的啊!

rpm包命名规则

二进制包常见格式:software_name-VERSION-[release].[os].arch.rpm

LABEL DESC
software_name 软件名称,以nodejs-6.17.1-1.el7.x86_64.rpm为例,名称是 nodejs
VERSION 软件版本信息,一般表示为mojor.minor[.patch|-patch],具体的意思跟JavaScript三段式命名包是对应的,以nodejs-6.17.1-1.el7.x86_64.rpm为例,软件版本信息是 6.17.1-1
release 这个位置代表的比较多,一般常见的alpha(内测)、beta(公测)和 release(发行)
os 支持的操作系统版本,以nodejs-6.17.1-1.el7.x86_64.rpm为例,el7表示支持的操作系统版本为Red Hat 7.x, CentOS 7.x`等
arch 表示当前包所支持的硬件平台类型,常见的类型见下图,以nodejs-6.17.1-1.el7.x86_64.rpm为例,x86_64表示支持x86 64 位

centos之rpm包管理器全解-编程知识网

图片来自《鸟哥的Linux私房菜》

rpm数据库

rpm在文件安装完毕后,会将安装的程序包的依赖、安装位置、配置文件等等的信息存储在/var/lib/rpm/目录下,这个目录也被称作rpm的数据库。这个目录内的信息很重要,因为未来如果我们有任何软件升级的需求,版本之间的比较就是来自于这个数据库,而且你想要查询系统已经安装的软件也是从这里查询的。

centos之rpm包管理器全解-编程知识网

图片来自《鸟哥的Linux私房菜》

安装程序包

命令格式:

rpm {-i|--install} [install-options] PACKAGE_FILE ...

通常来说使用ivh的选项来安装程序包足以应付大多数情况,即 rpm -ivh PACKAGE_FILE,也有一些其他的常用指令用来设置程序包的安装。

选项 作用
-v 通用选择项,输出安装过程的详细信息
-vv 通用选择项,输出更多安装过程的详细信息
-h hash marks 输出进度条,每个 # 表示 2% 的进度
–test 安装测试,用于检查与报告该软件潜在的依赖冲突或者是否可以安装到当前环境
–prefix 指定软件包的安装路径,而不是使用rpm的默认安装路径,比如--prefix=/usr/local表示软件将被安装到/usr/local路径中
–nodeps 忽略依赖关系,直接安装,此操作可能导致安装完成,程序因为缺少依赖而无法运行
–replacepkgs 重新安装程序包,默认不覆盖原有(同名)配置文件,如果需要覆盖配置文件,就需要将原有配置文件删除或者重命名。
–replacefiles 重新安装程序包,与replacepkgs不同的是,使用该参数会覆盖所有配置文件,且过程不可逆
–force --replacepkgs--replacefiles的综合体
–nosignature 不检查包签名信息,不检查来源合法性
–nodigest 不检查包的完整性
–noscripts 不想在程序安装过程中执行预定义的指令,可以使用此参数禁止所有钩子脚本的执行

rpm 包是可以自带钩子脚本的,钩子脚本的执行时机和名称如下表,可以使用命令 --noscripts 参数来一次禁止四个钩子脚本的执行。

时机 说明 名称 禁止执行的选项
preinstall 安装前执行的脚本 %pre –nopre
postinstall 安装后执行的脚本 %post –nopost
preuninstall 卸载前执行的脚本 %preun –nopreun
postuninstall 卸载后执行的脚本 %postun –nopostun
sudo rpm -ihv --replacepkgs zsh-lovers-0.9.0-1.el7.noarch.rpm # warning: zsh-lovers-0.9.0-1.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY
# Preparing...                          ################################# [100%]
# Updating / installing...
#    1:zsh-lovers-0.9.0-1.el7           ################################# [100%]

可以安装某个可信网络上的程序包rpm -ivh http://www.xxx.com/path/xxxx.rpm

升级

# 升级或安装,如果没有安装,则直接安装,如果已经安装,就做升级
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...
# 只能做升级
rpm {-F|--freshen} [install-options] PACKAGE_FILE ...

升级命令常见的使用格式

# 升级或安装
rpm -Uvh PACKAGE_FILE ...
# 升级
rpm -Fvh PACKAGE_FILE ...
选项 作用
–oldpackage 降级安装
–force 强制升级,原来版本被其他的程序所依赖,无法升级的时候,使用改选项强制升级。

其他选项和上一组的安装基本相同

  1. 不要对内核进行升级升级操作,内核1.0之前的版本如果要使用,需要重启系统才能使用,万一不兼容,系统就起不来了。如果确实需要使用新版内核,可以直接安装新版内核,linux 支持多版本内核共存。
  2. 如果原程序包的配置文件被修改过,升级时,新版本的程序提供的配置文件(如果同名)不会覆盖原有版本的配置文件,而是将新版本的配置文件(如果同名)重命名后提供(命名格式为FILE_NAME.rpmnew)后提供,如果不同名则直接安装。

卸载

rpm {-e|--erase} [--allmatches] [--justdb] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ...
选项 作用
–allmatches 卸载所有匹配指定程序包的各版本
-nodeps 不管依赖,强行卸载
–test 测试卸载

注意卸载使用的程序包的名称,而不是像安装和升级一样的,是程序文件的名称。

查询

所有的查询操作都是基于rpm数据库来实现的。

命令格式:

rpm {-q|--query} [select-options] [query-options] PACKAGE_NAME

select-options

rpm -q wget
# wget-1.14-18.el7_6.1.x86_64#列出所有已安装的程序包
rpm -qa 
#systemd-sysv-219-62.el7_6.6.x86_64
#polkit-pkla-compat-0.1-4.el7.x86_64
#grub2-tools-minimal-2.02-0.76.el7.centos.1.x86_64
#...
选项 作用
-a , –all 所有已安装程序包的列表
-f FILE_PATH 查询指定的文件是由那个程序包安装生成的,如查询/etc/bashrc是由那个程序包生成的
rpm -qf /etc/bashrc输出setup-2.8.71-10.el7.noarch
–whatprovides CAPABILITY 查询指定的 能力(CAPABILITY ) 由那个程序包提供
–whatrequires CAPABILIT 查询指定 CAPABILITY 被哪个包所依赖
-p , –package PACKAGE_FILE 对于未安装的程序包执行查询操作,具体查询什么内容,需要quer-options来指定。
# 查询 zsh  安装后,会生成那些文件
rpm -qpl zsh-5.8-1-omv4002.x86_64.rpm 
# 查询 bash 是有那个包提供的能力
rpm -q --whatprovides bash
# bash-4.2.46-31.el7.x86_64# 查询 /etc/lvm/lvm.conf 文件是由那个程序包生成的
rpm -qf /etc/lvm/lvm.conf 
# lvm2-2.02.186-7.el7_8.2.x86_64# 查询 bash 的能力被那些包所依赖
rpm -q --whatrequires bash
# dracut-033-554.el7.x86_64
# initscripts-9.49.46-1.el7.x86_64
# rsyslog-8.24.0-34.el7.x86_64
# bash-completion-2.1-6.el7.noarch
# lvm2-2.02.186-7.el7_8.2.x86_64

query-options

选项 作用
–changelog 查询 rpm 包的 changelog,注意这里不是源码包的 changelog
-l , –list 安装包生成的所有文件列表
-i , –info 程序包相关的信息,版本号、大小、所属的包租等信息
-c , –configfiles 查看程序包提供的配置文件
-d , –docfiles 查询指定程序包的帮助文档所在位置
–provides 列出指定的程序包提供了那些能力
-R , –requires 查询指定程序包依赖于那些能力
–scripts 查询指定的程序包自带了那些脚本

校验

校验功能主要在与提供系统管理员一个有用的管理机制,是对比rpm数据库的内容和当前系统中实际的软件包来实现的,如果有数据不小心丢失,或者误删了某个文件,误修改了某个文件,都可以使用这种方法来验证。

命令格式:

rpm {-V|--verify} [select-options] [verify-options] PACKAGE_NAME

校验程序包是否被修改,select-options 同上

# 没有输出就说明没有修改
rpm -V wget
# 编辑一下 wget 的readme 文件
file /usr/share/doc/wget-1.14/README
# /usr/share/doc/wget-1.14/README: ASCII text
sudo vi /usr/share/doc/wget-1.14/README
# 重新做一下校验
rpm -V wget
# S.5....T.  d /usr/share/doc/wget-1.14/README

被修改的详情及内容:

S :(file Size differs) 档案的容量大小是否被改变
M :(Mode differs) 档案的类型戒档案的属性 (rwx) 是否被改变?如是否可执行等参数已被改变
5 :(MD5 sum differs) MD5 这一种挃纹码的内容已经丌同
D :(Device major/minor number mis-match) 装置的主/次代码已经改变
L :(readLink(2) path mis-match) Link 路径已被改变
U :(User ownership differs) 档案的所属人已被改变
G :(Group ownership differs) 档案的所属群组已被改变
T :(mTime differs) 档案的建立时间已被改变

经过验证的功能,就可以知道那个文件在安装后被改动过,如果是计划中的改动,那就没什么问题,如果是意外的改动,就需要注意了,尤其是这种非正常变动的是二进制执行文件。有可能被入侵。

数字签名

前一节的校验主要用来针对的是软件包安装之后文件的修改检查,如果要对软件包的来源做合法性验证和完整性验证,则主要是通过rpm上的数字签名来实现的。

CentOS 使用的数字签名系统为 GNU 计划的 GnuPG(GNU Privacy Guard, GPG)(注 1)。 GPG 可以透过哈希运算,算出独一无二的专属密钥系统或者数字签名系统。

签名的大概过程是这样的:

  1. 提取程序包的特征码
  2. 使用自己的私钥对第一步提取出来的特征码进行加密,将加密后获得的字符串附加到程序包上。
  3. 验证程序包的时候,首先使用和第一步相同的方式提取特征码,然后使用软件包的制作者提供的公钥对第二步附加的加密特征码进行解密,然后对比两者是否相同。

在系统的/etc/pki/rpm-gpg文件夹中,可以找到系统中已经导入的所有的公钥。

$ ls -l /etc/pki/rpm-gpg
#total 56
#-rw-r--r--. 1 root root 1690 May 17  2018 RPM-GPG-KEY-CentOS-7
#-rw-r--r--. 1 root root 1004 May 17  2018 RPM-GPG-KEY-CentOS-Debug-7
#-rw-r--r--. 1 root root 1057 Oct 29  2018 RPM-GPG-KEY-CentOS-SIG-SCLo
#-rw-r--r--. 1 root root 1690 May 17  2018 RPM-GPG-KEY-CentOS-Testing-7
#-rw-r--r--. 1 root root 5969 Mar 23  2016 RPM-GPG-KEY-mysql
#-rw-r--r--. 1 root root 1463 Jul 15  2014 RPM-GPG-KEY-nginx
# ...$ cat RPM-GPG-KEY-nginx
#-----BEGIN PGP PUBLIC KEY BLOCK-----
#Version: GnuPG v2.0.14 (GNU/Linux)
#
#mQENBE5OMmIBCAD+FPYKGriGGf7NqwKfWC83cBV01gabgVWQmZbMcFzeW+hMsgxH
#W6iimD0RsfZ9oEbfJCPG0CRSZ7ppq5pKamYs2+EJ8Q2ysOFHHwpGrA2C8zyNAs4I
#QxnZZIbETgcSwFtDun0XiqPwPZgyuXVm9PAbLZRbfBzm8wR/3SWygqZBBLdQk5TE
#fDR+Eny/M1RVR4xClECONF9UBB2ejFdI1LD45APbP2hsN/piFByU1t7yK2gpFyRt
#a2V5IDxzaWduaW5nLWtleUBuZ2lueC5jb20+iQE+BBMBAgAoBQJOTjJiAhsDBQkJ
#...
#...
#-----END PGP PUBLIC KEY BLOCK-----

从上面的结果可以看出,公钥文件保存的也是一串字符串。

公钥

  1. 获取公钥

    除了centos官方光盘根目录自带公钥文件外,来自第三方组织的程序包的公钥需要到对应第三方的网站去下载。

  2. 导入公钥

    rpm --import 公钥路径
    
  3. 使用公钥

    一般情况下,若导入了对应组织的公钥,在安装程序包的时候,会自动进行验证。也可以使用命令来针对性的验证具体的程序包。

    rpm -K xxx.rpm
    
    # 没有对应公钥的时候,验证不通过
    rpm -K ~/rpm/nodejs-6.17.1-1.el7.x86_64.rpm 
    #/home/vagrant/rpm/nodejs-6.17.1-1.el7.x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#352c64e5) 
    

数据库重建

数据库的默认目录在这里/var/lib/rpm/

$ ls -l /var/lib/rpm
# total 83128
# -rw-r--r--. 1 root root  5275648 6月  10 19:24 Basenames
# -rw-r--r--. 1 root root     8192 5月  30 07:57 Conflictname
# -rw-r--r--. 1 root root   286720 6月  10 19:26 __db.001
# -rw-r--r--. 1 root root    90112 6月  10 19:26 __db.002
# -rw-r--r--. 1 root root  1318912 6月  10 19:26 __db.003
# -rw-r--r--. 1 root root  2756608 6月  10 19:24 Dirnames
# ...

命令格式

rpm {--initdb | --rebuilddb } [options]
选项 作用
–initdb 如果系统上没有rpm数据库,则初始化一个新的。如已经存在rpm数据库,则此命令不做任何操作
–rebuilddb 通过读取当前系统上所有的已安装包,来进行重新构建数据库

options

选项 作用
–dbpath 指定重建数据库的目录,如果不想使用默认目录的时候
# 初始化数据库到 /tmp/rpminitdbmkdir /tmm/rpminitdbrpm --initdb --dbpath=/tmp/rpminitdbll /tmp/rpminitdb
# total 416
# -rw-r--r--. 1 vagrant vagrant   8192 6月  11 10:19 Basenames
# -rw-r--r--. 1 vagrant vagrant   8192 6月  11 10:19 Conflictname
# -rw-r--r--. 1 vagrant vagrant 286720 6月  11 10:19 __db.001
# -rw-r--r--. 1 vagrant vagrant  90112 6月  11 10:19 __db.002
# -rw-r--r--. 1 vagrant vagrant 107048 6月  11 10:19 __db.003
# -rw-r--r--. 1 vagrant vagrant   8192 6月  11 10:19 Dirnames
# ...

获取需要的程序包

  1. 系统发行版的光盘或者官方的文件服务器,或者镜像站点

    http://mirrors.aliyun.com

    http://mirrors.163.com

    http://mirrors.ustc.edu.cn

  2. 项目的官方站点

  3. 第三方组织

    epel : 除红帽官方外,最可信任的组织

  4. 专门搜索rpm包的搜索引擎
    http://rpmfind.net
    http://rpm.pbone.net
    http://pkgs.org

  5. 自己动手,编译

建议对每一个来源程序包都做完整性校验。

<完>