1. 程序包管理器的功能
我们知道,由程序员编写并提供的程序源代码要转换成目标二进制格式才能在计算机上运行起来,但用户要在平台上使用时需要手动编译安装后才能使用,对于普通用户来说有一定难度。因此为了降低普通用户对应用程序的使用难度,程序员可在提供源代码的同时提供已在特定环境下编译好的程序文件,只要用户的平台环境和程序员的平台环境相同,就可以通过解压程序员提供的二进制格式文件即可使用,而无需自己手动编译安装。
一个已编译好的程序由二进制程序、库文件、配置文件和帮助手册等组成,而程序包管理器的功能就是将编译好的应用程序的各组成文件(二进制程序、库文件、配置文件、帮助文件等)打包成一个或几个程序包文件,从而更方便地实现程序包的安装、升级、卸载和查询等管理操作。
2. 源码到程序包的转换过程
3. rpm包管理器概述
rpm是Redhat公司针对自己的操作系统RHEL提出的一种管理软件包的方法,rpm原来全称为RedHat Package Manager,后来由于rpm包管理器的使用方便以及Redhat公司采取各种商业策略,使得rpm成为了工业标准,其他系统可借鉴使用rpm,因此rpm全称后来改为:RPM Package Manager。在系统上只要安装了rpm包管理器,那么只要符合rpm标准的程序包文件都可以实现更为方便地安装、升级、卸载和查询等管理操作。
4. 为什么要使用rpm?
Linux的哲学思想之一是“一个程序只做一件事,并且做好”。因此Linux经常通过使用众多功能单一的程序来完成复杂任务,最常见的例子是管道命令的使用。而各个程序功能的单一,带来的问题是各个程序文件之间的产生了极大的依赖性,这是一个需要解决的问题。此外,要安装各种功能的程序,而各程序在安装时的路径、生成的文件各不相同,这给卸载某程序将带来极大麻烦,极不方便管理,以及对程序的版本的管理等。在Linux上只要安装rpm包管理器即可解决以上问题,rpm包管理器可将编译好的各个应用程序组成文件打包成一个或有限个rpm程序包,每个包中会记录当前包的依赖性。一旦程序包安装了之后,rpm会追踪其各个文件的安装路径(包括程序运行时产生的临时文件)。rpm包管理器就是通过这种方式来实现对rpm程序包的管理的,而对程序包的管理无外乎是安装、升级、卸载、查询等操作。
5. 程序包管理器的组成部分
程序包管理器由程序包组成清单和数据库两部分组成:
(1)程序包的组成清单(每个程序都单独实现):
①文件清单
②安装或卸载时运行的脚本
(2)数据库(为所有rpm程序包所共用):
①程序包的名称和版本
②依赖关系
③功能说明
④安装生成的各个文件的文件路径及校验码信息
6. rpm包命名格式
rpm包有主包和支包(主包的子包)之分,支包作为主包的功能性补充。其中rpm主包的命名格式为:name-VERSION-release.arch.rpm。各个部分解释如下:
name:程序名
VERSION:版本
VERSION由三部分组成:
①major:程序的主版本号
②minor:程序的次版本号
③release:程序的修订号
release[.os].arch:代表rpm包的发行号
①release[.os]:rpm版本+操作系统
②arch:archetecture,支持的硬件架构。常见的硬件架构有i386, x64(amd64), ppc, noarch(支持任何架构)等
举个例子,zsh-5.0.2-25.el7.x86_64.rpm代表:该zsh程序包的主版本号为5,次版本号为0,修订号为2;rpm的版本号为25,支持的操作系统是RHEL 7(CentOS 7),支持的硬件架构是x86_64。
对于支包来说,其命名格式为:
name-function-VERSION-release.arch.rpm
常见的function有:devel, utils(工具程序), libs, ...
7. 获取程序包的途径
如何获取rpm包呢?
(1)系统发行版的光盘或官方的文件服务器(或镜像站点)
常见的镜像网站如:
http://mirrors.aliyun.com
http://mirrors.sohu.com
http://mirrors.163.com
(2)项目的官方站点
(3)第三方组织
(a)EPEL
(b)搜索引擎
http://pkgs.org
http://rpmfind.net
http://rpm.pbone.net
...
(4)自己制作rpm包
建议:检查其合法性(来源合法性、程序包的完整性)
8. CentOS系统上rpm命令管理程序包
8.1. 安装
语法格式:
rpm {-i|--install} [install-options] PACKAGE_FILE ...
常用命令选项:
-v:verbose,输出详细的过程信息;
-vv:very verbose,输出更为详细的过程信息;
安装选项(install-options):
-h:hash marks输出进度条;hash标记符为#,每个#表示2%的进度;
--test:测试安装,检查并报告依赖关系及冲突信息等;相当于dry run;
--nodeps:忽略依赖关系,不建议使用;
--replacepkgs:重新安装;
--noscripts:指定不运行脚本;
--nosignature:不检查包签名信息,即不检查程序包的来源合法性;
--nodigest:不检查包完整性信息;
用法:
rpm -ivh PACKAGE_FILE ...
注意:rpm可以自带脚本
最多有四类脚本:(--noscripts可指定不运行这四类脚本)
preinstall:安装过程开始之前运行的脚本,%pre;--nopre可指定不运行;
postinstall:安装过程完成之后运行的脚本,%post;--nopost可指定不运行;
preuninstall:卸载过程真正开始执行之前运行的脚本,%preun;--nopreun可指定不运行;
postuninstall:卸载过程完成之后运行的脚本,%postun;--nopostun可指定不运行;
命令演示:
安装zsh,首先挂载光盘:
[[email protected] ~]# mkdir /media/cdrom [[email protected] ~]# mount /dev/sr0 /media/cdrom mount: block device /dev/sr0 is write-protected, mounting read-only
用rpm下载zsh:
[[email protected] ~]# cd /media/cdrom/Packages/ [[email protected] Packages]# rpm -ivh zsh-4.3.11-4.el6.centos.2.x86_64.rpm Preparing... ########################################### [100%] 1:zsh ########################################### [100%]
8.2. 升级
语法格式:
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...
rpm {-F|--freshen} [install-options] PACKAGE_FILE ...
常用选项:
-U:升级或安装;
-F:升级;
-v:同“安装”;
-vv:同“安装”.
安装选项(install-options):
--oldpackage:降级 --> 某些程序升级后遇到不兼容的情况,此时需要降级;
--force:强制升级 --> 某些程序升级后会引起依赖性问题,此时可能会用到此选项;
其他安装选项同“安装”。
用法:
rpm -Uvh PACKAGE_FILE ...
rpm -Fvh PACKAGE_FILE ...
注意:
(1)Linux支持多内核版本并存,所以不要对内核做升级操作,因为这样有可能会导致无法“回滚”,建议直接安装新版本内核即可。
(2)如果某原程序包的配置文件安装后曾被修改过,则在升级时,新版本的程序提供的同一个配置文件不会覆盖原有版本的配置文件,而是把新版本的配置文件重命名(FILENAME.rpmnew)后提供;
命令演示:
查看当前已安装的zsh的版本:
[[email protected] ~]# rpm -q zsh zsh-4.3.11-4.el6.centos.2.x86_64
从网易镜像站点下载zsh-5.0.2-25.el7_3.1.x86_64.rpm程序包:
[[email protected] ~]# wget http://mirrors.163.com/centos/7/updates/x86_64/Packages/zsh-5.0.2 25.el7_3.1.x86_64.rpm
用rpm升级zsh:
[[email protected] ~]# rpm -Uvh zsh-5.0.2-25.el7_3.1.x86_64.rpm warning: zsh-5.0.2-25.el7_3.1.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5 : NOKEY error: Failed dependencies: libc.so.6(GLIBC_2.14)(64bit) is needed by zsh-5.0.2-25.el7_3.1.x86_64 libc.so.6(GLIBC_2.15)(64bit) is needed by zsh-5.0.2-25.el7_3.1.x86_64
发现有依赖关系导致无法升级。
此时若要强行升级可使用--nodeps选项:
[[email protected] ~]# rpm -Uvh --nodeps zsh-5.0.2-25.el7_3.1.x86_64.rpm warning: zsh-5.0.2-25.el7_3.1.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5 : NOKEY Preparing... ########################################### [100%] 1:zsh ########################################### [100%]
注意:忽略依赖性升级后程序不一定能正常运行!
再将zsh降级:
[[email protected] ~]# cd /media/cdrom/Packages/ [[email protected] Packages]# rpm -Uvh --oldpackage zsh-4.3.11-4.el6.centos.2.x86_64.rpm Preparing... ########################################### [100%] 1:zsh ########################################### [100%]
8.3. 卸载
语法格式:
rpm {-e|--erase} [--allmatches] [--nodeps] [--test] PACKAGE_NAME ...
卸载选项(erase options):
--allmatches:卸载所有匹配指定名称的程序包的各版本;
--nodeps:忽略依赖关系;
--test:测试卸载,dry run模式。
用法:
rpm -e PACKAGE_NAME
命令演示:
卸载已安装的zsh程序包:
[[email protected] ~]# rpm -e zsh
如果没有任何显示就说明卸载成功了!
8.4. 查询
语法格式:
rpm {-q|--query} [select-options] [query-options]
[select-options]:
PACKAGE_NAME:查询指定的程序包是否安装,及其版本;
-a, --all:查询所有已经安装过的包;
-f, --file FILE:查询指定的文件由哪个程序包安装生成;
-p, --package PACKAGE_FILE:用于实现对未安装的程序包执行查询操作;
--whatprovides CAPABILITY:查询指定的CAPABILITY由哪个程序包提供;
--whatrequires CAPABILITY:查询指定的CAPABILITY被哪个包所依赖。
[query-options]:
--changelog:查询rpm包的changelog;
-i, --info:程序包相关的信息,版本号、大小、所属的包组等
-l, --list:程序包安装生成的所有文件列表;
-c, --configfiles:查询指定的程序包提供的配置文件;
-d, --docfiles:查询指定的程序包提供的文档;
--provides:列出指定的程序包提供的所有的CAPABILITY;
-R, --requires:查询指定的程序包的依赖关系;
--scripts:查看程序包自带的脚本片段。
用法:
rpm -qi PACKAGE
rpm -qf FILE
rpm -qc PACKAGE
rpm -qd PACKAGE
rpm -qpi PACKAGE_FILE
rpm -apl PACKAGE_FILE
rpm -qpc PACKAGE_FILE
列了这么多个选项,不如来个实例吧!
(1)查看zsh是否已经安装:
[[email protected] ~]# rpm -qa | grep ‘^zsh‘ zsh-4.3.11-4.el6.centos.2.x86_64 //显示已安装zsh; 或: [[email protected] ~]# rpm -q zsh zsh-4.3.11-4.el6.centos.2.x86_64 //显示已安装zsh;
(2)查询/etc/fstab由哪个程序包安装生成:
[[email protected] ~]# rpm -qf /etc/fstab setup-2.8.14-20.el6_4.1.noarch
(3)列出安装httpd生成的所有文件列表:
[[email protected] ~]# rpm -ql httpd
(4)列出httpd程序包的依赖关系:
[[email protected] ~]# rpm -qR httpd /bin/bash /bin/sh .....(省略)..... libz.so.1()(64bit) rpmlib(CompressedFileNames) <= 3.0.4-1 .....(省略)..... rpmlib(VersionedDependencies) <= 3.0.3-1 rtld(GNU_HASH) system-logos >= 7.92.1-1 rpmlib(PayloadIsXz) <= 5.2-1
(5)查看httpd程序包提供的文档:
[[email protected] ~]# rpm -qd httpd /usr/share/doc/httpd-2.2.15/ABOUT_APACHE /usr/share/doc/httpd-2.2.15/CHANGES /usr/share/doc/httpd-2.2.15/LICENSE /usr/share/doc/httpd-2.2.15/NOTICE /usr/share/doc/httpd-2.2.15/README /usr/share/doc/httpd-2.2.15/VERSIONING /usr/share/man/man8/apachectl.8.gz /usr/share/man/man8/htcacheclean.8.gz /usr/share/man/man8/httpd.8.gz /usr/share/man/man8/rotatelogs.8.gz /usr/share/man/man8/suexec.8.gz
(6)查询httpd程序包提供的配置文件:
[[email protected] ~]# rpm -qc httpd /etc/httpd/conf.d/welcome.conf /etc/httpd/conf/httpd.conf /etc/httpd/conf/magic /etc/logrotate.d/httpd /etc/sysconfig/htcacheclean /etc/sysconfig/httpd /var/www/error/HTTP_BAD_GATEWAY.html.var /var/www/error/HTTP_BAD_REQUEST.html.var .....(以下省略).....
(7)查看httpd程序包自带的脚本片段:
[[email protected] ~]# rpm -q --scripts httpd
(8)列出bash程序包提供的所有的CAPABILITY:
[[email protected] ~]# rpm -q --provides bash config(bash) = 4.1.2-40.el6 bash = 4.1.2-40.el6 bash(x86-64) = 4.1.2-40.el6
(9)查看httpd程序包提供的所有的CAPABILITY:
[[email protected] ~]# rpm -q --provides httpd config(httpd) = 2.2.15-53.el6.centos httpd-mmn = 20051115 httpd-suexec = 2.2.15-53.el6.centos .....(中间省略)..... mod_vhost_alias.so()(64bit) webserver .....(以下省略).....
(10)查询指定的CAPABILITY (这里为webserver)由哪个程序包提供:
[[email protected] ~]# rpm -q --whatprovides webserver httpd-2.2.15-53.el6.centos.x86_64
(11)查询指定的CAPABILITY (这里为bash)被哪个包所依赖:
[[email protected] ~]# rpm -q --whatrequires bash jline-0.9.94-0.8.el6.noarch initscripts-9.03.53-1.el6.centos.x86_64 dracut-004-409.el6.noarch lvm2-2.02.143-7.el6.x86_64 rsyslog-5.8.10-10.el6_6.x86_64 cronie-1.4.4-15.el6_7.1.x86_64 autofs-5.0.5-122.el6.x86_64 eclipse-pde-3.6.1-6.13.el6.x86_64
(12)查看bash的更新日志(changelog):
[[email protected] ~]# rpm -q --changelog bash ... * Fri Oct 17 1997 Donnie Barnes <[email protected]> - added BuildRoot * Tue Jun 03 1997 Erik Troan <[email protected]> - built against glibc
(13)查看程序包相关的信息,版本号、大小、所属的包组等:
[[email protected] ~]# rpm -qi zsh
8.5. 校验
用途:可检查程序包中的数据是否被修改过。
语法格式:
rpm {-V|--verify} [select-options] [verify-options]
用法:
rpm -V PACKAGE_NAME
校验属性:
S file Size differs M Mode differs (includes permissions and file type) 5 digest (formerly MD5 sum) differs D Device major/minor number mismatch L readLink(2) path mismatch U User ownership differs G Group ownership differs T mTime differs P caPabilities differ
命令演示:
修改zsh程序包的配置文件,首先查看zsh程序包的配置文件有哪些:
[[email protected] ~]# rpm -qc zsh /etc/skel/.zshrc /etc/zlogin /etc/zlogout /etc/zprofile /etc/zshenv /etc/zshrc
用vim修改/etc/zshrc文件,在首行添加一个‘#‘字符,然后再用-V选项检验:
[[email protected] ~]# vim /etc/zshrc [[email protected] ~]# rpm -V zsh S.5....T. c /etc/zshrc
显然,文件/etc/zshrc的大小、md5值、时间戳(mtime)发生了变化。
8.6. 数据库重建
默认rpm管理器的数据库路径为/var/lib/rpm,刚才的查询操作正是通过此处的数据库进行。
获取帮助:
CentOS 6:man rpm
CentOS 7:man rpmdb
语法格式:
rpm {--initdb|--rebuilddb} [-v] [--dbpath DIRECTORY] [--root DIRECTORY]
常用选项:
--initdb:初始化数据库,当前无任何数据库可初试化创建一个新的数据库;当前有时不执行任何操作;
--rebuilddb:重新构建,通过遍历读取当前系统上所有已经安装过的程序包进行重新创建;
命令演示:
在/tmp/mydb目录下创建初始化数据库:
[[email protected] ~]# rpm --initdb --dbpath /tmp/mydb [[email protected] ~]# ls /tmp/mydb/ __db.001 __db.002 __db.003 __db.004 Packages
在/tmp/mydb目录下重新创建数据库:
[[email protected] ~]# rpm --rebuilddb --dbpath /tmp/mydb [[email protected] ~]# ls /tmp/mydb/ Packages
注意:不一定能够重建完整的数据库,所以慎用该命令吧!
8.7. 包来源合法性验证和完整性验证
首先要了解一下什么是数字签名?
数字签名就是用本地密钥去加密对应数据的特征码。
程序包开发者将程序包制作好之后,采用单向加密算法对程序包进行计算,得到定长特征码,再用私钥对这段定长特征值进行加密,并将加密过的特征码附于程序包尾部,这就是数字签名。程序使用者先得到开发者的公钥,用于解密特征码,如果解密成功,说明来源合法;然后使用者在本地对该程序包用单向加密算法再次计算出定长特征码,如果使用者计算出的特征码和程序开发者提供的特征码相同,则说明程序数据完整。虽然用了两种加密算法,但却没有保密性的概念,而是作为验证。
特征码有没有被篡改的可能性?假设中间人得到程序包的特征值后,想篡改特征码,但篡改后需要用本地私钥进行加密,因此来源就不合法了,更不用谈完整性了,所以特征码是无法修改的。
但存在一个问题,就是使用者如何获得正确的公钥?这要求下载公钥的网站的正确性以及数据在网络传输过程中的安全性,涉及网络安全问题。
图解数字签名:
对于CentOS发行版来说,假设已获取正确的公钥,那么导入信任的包制作者的公钥(或签名密钥)操作如下:
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
两种验证方式:
(1)安装此组织签名的程序时,程序内部会自动执行验证。
(2)手动验证:rpm -K PACKAGE_FILE,同样由程序内部自行执行校验操作。
命令演示:
校验zsh程序包的来源合法性及数据完整性:
[[email protected] Packages]# rpm -K zsh-4.3.11-4.el6.centos.2.x86_64.rpm zsh-4.3.11-4.el6.centos.2.x86_64.rpm: rsa sha1 (md5) pgp md5 OK //校验通过;