用rpm和dnf管理linux下的软件安装

linux下的软件安装对用户不太友好. 每次需要用的时候, 记不住命令, 都是现去搜索. 最近对Fedora-CentOS-RedHat系的软件包管理系统进行了稍微深入的学习了解. 这篇是自己的学习笔记. 目的是以后再需要使用的时候, 只需要读这一篇即可.

先明确一些概念:

  • File: 文件. 操作系统对存储数据的一个抽象.
  • Package: 软件包或简称包, 一些文件组成的集合.
  • Group: 包组, 一些包组成的集合.
  • Repository: 资源库, 存放大量互相兼容的包的空间. 跟library的翻译要区分开. 也要跟git等配置管理软件里的repository区分开.

起因

大部分Windows上的软件在安装的时候一般只会在C:\Program Files或用户指定的目录创建一个自己的目录. 互相不会影响. 每个软件通常也自己负责安装自己的所有依赖的第三方软件. 有时候两个软件都依赖于同一个库, 却各自安装自己的一个拷贝(不是所有软件都这么做). 而且被安装的软件自身就会提供一个反安装程序, 能够清除自己安装上的所有文件. (这里得排除恶意流氓软件和系统软件.) 这跟windows生来就是面向桌面用户有关, 打开程序通过点击图标即可. 大部分windows用户并不关心软件到底跟那些文件有关.

Linux上的软件通常把跟自己相关的文件分散的安装到系统的不同路径, 而且不会把依赖的第三方软件打包在自己的安装包里. 之所以这么安排, 有一定的历史原因. Linux的用户大部分是专业人士, 对这种不方便也不敏感.

当然Linux也提供了对软件安装进行管理的办法, 那就是包管理软件(package manager). 现在这种软件形成了两个流派, 一个是Debian-Ubuntu派使用的dpkg+apt, 一个是Fedora-CentOS-RedHat派使用的rpm+yumrpm+dnf

这篇文章主要记录的是rpm+dnf这种流派的各个方面.

要解决的问题

包管理软件应该提供的一些功能包括如下几条.

如果已经拥有了软件包, 用户需要

  1. 安装/升级/反安装 ->
  2. 查询一个包都有哪些文件, 安装后都放在哪. ->
  3. 安装了之后, 如果有一个文件, 也应该能查询到这个文件属于哪个包. ->
  4. 查看这个包依赖的其他包有那些, 是否被安装. ->
  5. 查看依赖于已经安装的这个包被哪些包依赖. ->

如果没有软件包, 用户需要:

  1. 如果知道软件名称, 或有个关键字, 可以在指定的资源库中查询是否有该包. ->
  2. 如果知道某一个文件名, 可以在指定的资源库中查询是否有包包含该文件. ->
  3. 可以自动下载安装某个包以及其依赖的其他包. ->
  4. 可以单独下载该包, 不下载它依赖的其他包. ->

如果用户自己能够从源代码构建可执行文件, 用户需要:

  1. 做一个自己的软件包. ->
  2. 建立一个自己的资源库. ->
  3. 使自己的包满足别的软件的依赖. ->

rpm与dnf的关系

rpm原来是RedHat Package Manager的缩写, 后来模仿GNU改成递归式的名字RPM Package Manager.

rpm可以对一个独立的软件包进行安装, 反安装, 查询, 和验证. rpm软件包里包括当前软件的所有文件和一些叫做元数据(metadata)的信息. 元数据包括helper script, file attributes, 以及其他信息. rpm能够告诉用户当前包依赖哪些其他的软件包. 但不能帮助用户解决这些依赖关系.

rpm会维护一个已安装包的数据库. 以便于用户快速查询, 这个数据库存储在/var/lib/rpm下, 文件以__db开头.

dnf是基于rpm开发的更高一层的包管理软件. 除了rpm能够实现的功能外, 它把软件包组织成资源库, 可以帮用户查询资源库中未安装的软件包信息, 从指定资源库获取软件包. 自动处理依赖关系以安装或卸载软件包, 以及更新系统到资源库中最新可用版本.

rpm文件命名规范

rpm文件名遵循NAME-VERSION-RELEASE规范命名, 例如python-2.7.5-34.el7.x86_64.rpm, 包名是python, 版本是2.7.5, 34.el7.x86_64中34代表当前这个版本的发布次数, el7代表linux的发行版本(distribution), x86_64代表cpu架构(architecture). 下面的命令可以帮助查询distribution:

1
rpm --eval %{?dist}

cpu架构是由构建可执行文件的环境决定, 如果软件是跨平台的(architecture-independent)可以是noarch 查询当前电脑的cpu架构可以用如下命令:

1
rpm --eval %{_arch}

关于软件包的基本操作

下表列出了用户常用的rpm和dnf的基本操作

用户需求 rpm操作 dnf操作
安装 简单安装
rpm -i package.rpm12
安装一个软件包及其所有未安装的依赖包
dnf install package
输出更多信息以及进度条
rpm -ivh package.rpm
-v, --verbose, -h, --hash
同时安装多个软件包
dnf install package1 package2 ...
输出更多信息以及百分比
rpm -iv --percent package.rpm
仅下载不安装
dnf download package
同时下载所有未安装的依赖包
dnf download --resolve package
更新 删除旧版本之后安装新版本
rpm -Uvh new-package.rpm
更新单个包
dnf update package
更新成更旧的版本
rpm -Uvh --oldpackage old-version.rpm
检查需要更新的包
dnf check-update
如果没有旧版本则不安装(Freshen)
rpm -Fvh new-package.rpm
批处理更新(Freshen)
rpm -Fvh /fedora/updates/*.rpm
更新所有包及其依赖
dnf update
删除 简单删除
rpm -e package3
删除包及其所有依赖的包
dnf remove package ...
查询 简单查询
rpm -q package
搜索包
dnf search package
列出所有安装的包
rpm -qa
dnf list all
查询已安装包的所有信息
rpm -qi package
-i, --info
dnf info package
查询未安装包的所有信息
rpm -qip package.rpm
-p, --package
查询当前已安装包依赖于哪些文件或包
rpm -qR package
-R, --requires
查询已安装或未安装包依赖于哪些文件或包
dnf repoquery --requires package
查询当前未安装包依赖于哪些文件或包
rpm -qpR package.rpm
查询已安装或未安装包依赖于哪些包
dnf repoquery --requires --resolve package
查询哪些包依赖于当前已安装的包
rpm -q --whatrequires package
查询已安装或未安装包依赖于哪些文件或包
dnf repoquery --whatrequires package
查询文件属于哪个包
rpm -qf file
dnf provides file
列出已安装包安装了哪些文件
rpm -ql package
列出已安装包安装了哪些文件
dnf repoquery -l package
列出未安装包需要安装哪些文件
rpm -qlp package
包组相关操作 列出系统已安装包组和可用包组数量
dnf groups summary
列出系统已安装包组和可用包组
dnf group list
给出指定包组的信息
dnf group info "group name"
安装包组内所有包
dnf group install group_name
dnf group install groupid
删除包组内所有包
dnf group remove group_name
dnf group remove groupid
更新包组内所有包
dnf group update group_name

dnf关于资源库的基本操作

dnf的主要配置文件是/etc/dnf/dnf.conf, 该文件包含两部分:

  • "main"部分保存着dnf的全局设置.
  • "repository"部分保存着资源库的设置, 可以有一个或多个资源库.

另外在/etc/yum.repos.d目录里保存着一个或多个以.repo为后缀的资源库相关文件,它们也可以定义不同的资源库. 这些配置文件都为INI文件格式, 所有变量的帮助可以在DNF Configuration Reference中找到.

通过命令对资源库的常用操作在下面列出:

操作 命令
列出所有已激活的资源库 dnf repolist, 添加--all或者--disabled选项可以选择列出所有的或者未激活资源库. 再加-v可以显示更多信息.
显示当前的main配置信息 dnf config-manager --dump
显示某个资源库的配置信息 dnf config-manager --dump repoid
添加资源库 dnf config-manager --add-repo repository_url
激活资源库 dnf config-manager --set-enable repository
禁用资源库 dnf config-manager --set-disable repository
查看config-manager手册 man dnf-config-manager

如何建立RPM包

如果用户可以自己从源代码构建可执行文件, 那么就可以自己建立RPM包. 有一篇RPM Packaging GuideFedora RPM Guide里面有详细的介绍.

如何建立本地资源库

TBD

参考


  1. rpm命令中, 上面个提到的package.rpm都可以是网络地址, 比如ftp://user:pass@ftpserver/directory/package.rpm或者http://webserver/dir/remote-package.rpm↩︎

  2. rpm命令中, 使用--test跟其他选项组合, 可以虚拟的执行该动作, 配合-vv选项, 可以用来调试.↩︎

  3. 这里package可以是仅仅上上文rpm文件命名规范里提到的NAME, 也可以带上VERSIO和(或)RELEASE↩︎