一、软件包的管理器组成

    红帽(RedHat)的软件包管理器是rpm——Redhat Package Manager,它能够将程序包所需要的任何文件都封装成一个单独的个体,安装时按照需要展开、规划和部署到相关的位置。由于红帽的软件包管理器日益流行,很多其他的操作系统也会使用rpm,因此rpm不再表示Redhat Package Manager,而指代一个递归的缩写——RPM is Package Manager。尽管不同的操作系统都使用rpm软件包管理器,但不等于rpm可以互相兼容,因为不同的操作系统,其组织结构不相同。

一个软件包的组成部分主要有以下四类:

A.二进制程序,通常安装在{/bin,/sbin}{/usr/bin, /usr/sbin}{/usr/local/bin,/usr/local/sbin}下,通常他们是成对出现的,即同时安装在/bin/sbin下,而不会同时安装在/bin /user/sbin下。

B.库文件:程序的运行依赖于库文件,Linux的核心库是glibc,但很多软件也会将自己的核心文件封装成库文件,以供其他程序调用或二次开发。而库文件也是可执行程序,但不能直接执行,因为库文件没有执行入口,只能被其他文件调用执行。在开发时,这些库其实是函数(即非main的函数)。它们通常安装在/lib, /usr/lib,/usr/local/lib等路径下。Linux下的库分为静态库和动态库,静态库通常以“.a”结尾,动态库通常以“.so”结尾。

C.配置文件:用来定义程序的特性。配置文件通常是纯文本文件(多用于简单的配置,存放一组简单的参数,如:directive=value)或xml(较复杂的环境,如tomcat的配置文件,用于服务器上的交互)格式的文件,存放在/etc或其他指定的路径下。

D.帮助文件:手册(如/usr/share/man,帮助命令man通常就是到该目录下查询帮助信息,而man命令也有自己的配置文件,在/etc/man.config中,使用MANPATH来定义man的查询路径),README(功能、研发时间、开发者等等), INSTALL(安装),多存放于/usr/share/doc/中。

 

二、软件包管理工具

软件包管理工具(RPM)用来管理软件包的各种文件,它需要包括以下内容:1.文件清单 2.文件放置路径 3. 提供的功能说明4.依赖关系

如果要卸载软件包,则需要知道软件包的每一个文件的路径,这就需要软件包管理器提供一个整体程序的内置数据库,用来实现对当前系统上每一个程序的追踪和管理,这个数据中保留的信息主要有:1.当前安装的每一个程序2.每一个程序展开的文件3.每一个文件的路径4.每一个文件本身的MD5校验值等等。

RPM的主要功能包括:打包、安装、查询、升级、校验、卸载、数据库管理(重建)。打包的功能后文会详解,目前只介绍其他的五个功能。

 

三、其他安装方式

Linux系统上程序的安装方法并不仅仅局限于RPM包的安装,还有很多方式同样也可以安装程序:

1. 直接展开通用二进制格式

一些归档压缩的文件直接展开解压后就可以使用。

 

2. 使用前端工具yum安装

由于Linux的哲学思想是组合单一目的小程序来完成功能,这就导致了程序之前错综复杂的依赖关系,比如要安装程序x,必须先安装y,而安装y必须先安装mn,甚至有很多程序会循环依赖,比如要安装x必须先安装y,而要安装y必须先安装x,如果要解决这样的矛盾,可能需要同时安装xy两个程序。为了解决这样的依赖关系,rpm软件包管理工具借鉴dpt的方式,开发了一个前端管理工具yumYellowDog),将所有的软件包依赖关系建成一个数据库,安装一个程序如果需要用到某个库文件,可以通过yum下载这些被依赖的库文件到本地。不过yum并不是一个独立的软件包管理工具,它需要依赖于rpm来使用。

 

3. 编译安装

并不是所有的程序都会制作成rpm软件包管理器,Linux早期更多的使用的是二进制编译安装的方式,即将源代码编译成二进制码。编译文件需要使用编译器,通常是gcc(编译c语言)或g++(编译c++)。而编译文件时要用到的库文件,必须确保本地已经提供了,即提供编译环境,也叫开发环境。卸载编译安装的文件必须手动逐一卸载每一个文件,因此建议采用编译安装时将所有的文件都集中到一个特定目录下,当然这样也会带来一些弊端:

1.二进制程序无法直接执行了,因为不在PATH环境变量的搜索路径之下了,因此只能手动执行了,要解决这个问题,需要修改PATH环境变量的路径;

2.系统无法找到库文件了。因为系统搜索库文件通常是在/lib/usr/lib下找,甚至连/usr/local/lib都不包含在操作系统的搜索范围之内。要让操作系统搜索特定的库文件,也需要修改配置文件,即/etc/ld.so.conf文件和/etc/ld.so.conf.d下所有以.conf结尾的文件,它定义了除标准库以外的其他库文件路径。

3.帮助手册也需要编辑配置文件/etc/man.config,使得man命令能找到相应的帮助信息,或者使用man-M来指定手册的打开路径

4.操作系统默认搜索头文件(指定函数名、函数个数、参数、参数类型、参数个数等等)的路径是/usr/include,如果采用编译安装,就需要将头文件的路径导出到系统搜索头文件的目录下,通常使用复制头文件和创建链接的方式。

 

四、RPM

1. 源程序的命名

源程序命名的基本格式为:PackageName-Version.tar.{gz|bz2|xz}

通常版本号(Version)有三个:major.minor.release——主版本号.次版本号.发行号。其中主版本号是程序的主要功能发生了巨大的改变时才使用;次版本号是在程序的部分功能有重大改变时使用,发行号是在修复了一些bug,调整了一些属性后进行的升级。因此使用程序之前,可以通过版本号来确定该程序是在哪一级别上完成的升级。以bash-4.3.1.tar.xz为例,其中4major号,3minor号,1release号。

 

源程序需要打包成RPM软件包,通常这种RPM包有两种,一种是源程序的包,一种是二进制的包,如果不加特别说明,指的是二进制的包。

 

2. RPM包的命名

RPM包也需要命名,且名字要同源程序的包名加以区别;同时由于RPM包是二进制的,这就需要标明该RPM包是安装在哪种平台上的,如PowerPCX86X86_64,甚至是无平台的。RPM包的格式为:

rpmName-Version-Release.Arc.rpm

    RPM包的Version号和源程序的版本号需要保持一致,但这里的Release号指的是RPM包的打包者第几次修正这个包,和源程序本身没有关系(同一个源程序可能会被制作多次),并且这个Release号可能会标明所适用的操作系统平台。Arc指的是安装在哪种主机平台上,常见的主机平台有:i686x86_64amd64ppcpowerPC)、noarch(不依赖平台)等。

如某一个RPM包的命名为 bash-4.3.2-5.el6.x86_64.rpm,那么就表明这是一个bash程序包;其源程序的主版本号为4,次版本号是3,发行号2;它是第5次修正的RPM包;这个包用在RedHat6Enterprise版上;适用于x86_64的主机平台。

 

3.RPM包的分包

RPM包的制作者可以对RPM包进行分包,因为一个程序可能会有许多功能,其中不少功能是用不上的,如某些程序提供了头文件,用来供程序员进行二次开发,而普通用户是不会对该程序进行二次开发的,故只需要安装该程序的配置文件和二进制文件就可以了,分包的优势就体现在这里:将程序的某些功能做成独立的包,如果需要,才安装。          RPM包可以分为主包(核心包)和分包(支包)。其中主包的包名遵循RPM包的基本命名规则,如bind-9.8.2-0.l7.rcl.el6.x86_64.rpm;而分包会在主包的基础上包含其功能,如bind-chroot-9.8.2-0.l7.rcl.el6.x86_64.rpm,这里的chroot就是分包的功能。

通常情况下,一个RPM包包括一个主包和一个开发包,如bindbind-devel,一些比较大的程序还会包括一些其他的包,如工具包bind-util,库文件bind-lib等等。

包的安装应根据实际需求来,但是不论是安装哪种程序,分包的运行都必须依赖于主包,比如bind-devel包必须依赖于bind包,故要安装bind-devel包,就必须先安装bind包。

 

4. 操作系统的安装

Linux系统的安装光盘上会找到一个packages目录,其中存放了安装系统所需要的rpm包,甚至连系统的内核也被做成了rpm包。操作系统的安装,实际上是安装光盘提供给用户一个安装程序,这个程序会让用户选择要安装的程序,如何进行分区格式化等等。当用户确认选择之后,该安装程序就会安装相应的rpm包。

 

5.获取rpm

Linux的系统安装光盘并不是万能的,有很多rpm包安装光盘并不提供,而一些需要安装的程序在网络上也只能找到源程序,这种情况下如果仍然希望通过rpm包的形式来安装,就需要寻求第三方的帮助,请他们制作相应的rpm包。红帽系统有专门的社区,能为epel(红帽5或红帽6)平台提供扩展包的制作,目前该项目由fedora来管理,故称为fedora-epel。除此之外,还有一些镜像也提供扩展包:

http://mirrors.sohu.com     

http://rpmfind.net

http://rpm.pbone.net/

并不是所有的rpm包来源都是安全可靠的,因此出于安全性考虑,应该首选光盘中的rpm包,其次是epel提供的包。

 

6.RPM包的验证机制

RPM包有其自身的验证机制,可以验证来源的合法性、包的完整性以及软件包自身的完整性。其中对来源合法性的验证是通过验证非对称性公钥加密的方式实现的,即gpg命令(gpg是对pgp——privacygard protect这种技术规范的开源实现)。

非对称加密有两个密钥,分别是公钥(pk)和私钥(sk)。使用公钥加密的,必须通过与之配对的私钥sk来进行解密,反之亦然,事实上公钥是从私钥中提取出来的。

由于非对称加密的执行速度非常慢,所以通常不用它来加密数据,而是用来作为数字签名或密钥交换。一个rpm包的体积比较大,并不适合对其进行整体加密,因此当制作了一个rpm包后,采用单向加密算法(md5,散列加密,sha1sha256sha512等)计算该rpm包的特征码,然后用这个rpm包的私钥对特征码进行加密,再将加密结果附加在rpm包后面。今后如果要验证这个rpm包是否合法,就需要对其进行解密,而对私钥的解密,只能是其公钥,反之,如果能用公钥解密,就说明一定是与之对应的私钥加密的。因此只要能用公钥解密,就说明加密者是rpm包的原作者,从而可以确认软件包的合法性。

进一步来说,当采用公钥对软件包进行解密后,得到的是软件包的特征码(散列值),这时如果使用同样的单向加密算法对该RPM包进行计算,能够得到软件包的特征码,用这个特征码和之前解密得到的特征码进行比较,如果一致,就说明软件包中还是原来的内容,如果不一致,就说明该RPM包被修改过了。RedHat官方制作的所有rpm包都提供了公钥,可以使用这个公钥来对一些来源不明的安装光盘进行验证,以确保其安全性。

下面来演示一下验证的过程:

 

[root@localhost~]# ls /etc/pki/rpm-gpg/

RPM-GPG-KEY-CentOS-6        RPM-GPG-KEY-CentOS-Security-6
RPM-GPG-KEY-CentOS-Debug-6  RPM-GPG-KEY-CentOS-Testing-6
#安装了操作系统后,会自动展开一个官方公钥


 

如果在/etc/pki/rpm-gpg下找不到带有Release字样的文件,那么普通文件RPM-GPG-KEY-CentOS-6即为公钥,只需要将该文件导入到RPM包上,就可以验证包的合法性。具体的导入操作如下:

[root@localhost~]# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6


如果现在要验证一个光盘中提供的rpm包,可以进行如下操作:

[root@localhost~]# mkdir /media/cdrom

[root@localhost~]# mount /dev/cdrom /media/cdrom

mount:block device /dev/sr0 is write-protected, mounting read-only

[root@localhost~]# cd /media/cdrom

[root@localhostcdrom]# ls

CentOS_BuildTag  isolinux                  RPM-GPG-KEY-CentOS-Debug-6
EFI              Packages                  RPM-GPG-KEY-CentOS-Security-6
EULA             RELEASE-NOTES-en-US.html  RPM-GPG-KEY-CentOS-Testing-6
GPL              repodata                  TRANS.TBL
p_w_picpaths           RPM-GPG-KEY-CentOS-6
#其实光盘中会提供公钥

[root@localhostcdrom]# cd Packages/

[root@localhostPackages]# ls

zlib-1.2.3-29.el6.x86_64.rpm
zlib-devel-1.2.3-29.el6.i686.rpm
zlib-devel-1.2.3-29.el6.x86_64.rpm
zsh-4.3.10-7.el6.x86_64.rpm

[root@localhostPackages]# cp zsh-4.3.10-7.el6.x86_64.rpm /u01/tutor/test

[root@localhostPackages]# cd /u01/tutor/test

[root@localhosttest]# ls

a.hadoop  a.hive b.hadoop  c.hadoop  fstab test.txt 
zsh-4.3.10-7.el6.x86_64.rpm

[root@localhosttest]# rpm -K zsh-4.3.10-7.el6.x86_64.rpm

zsh-4.3.10-7.el6.x86_64.rpm:rsa sha1 (md5) pgp md5 OK
#只要显示OK,说明校验是合法的

 

rpm命令除了用-K选项外,还可以用--checksig来定制检查的选项:

rpm {--checksig}[--nosignature] [--nodigest] PACKAGE_FILE ...

其中nosignature表示只检查完整性不检查合法性,nodigest表示只检查来源合法性不检测完整性。如:

[root@localhosttest]# rpm --checksig --nodigest zsh-4.3.10-7.el6.x86_64.rpm

zsh-4.3.10-7.el6.x86_64.rpm:rsa (md5) pgp OK
#只显示了pgp OK,没有显示md5 OK了

[root@localhosttest]# rpm --checksig --nosignature zsh-4.3.10-7.el6.x86_64.rpm

zsh-4.3.10-7.el6.x86_64.rpm:sha1 md5 OK
#没有显示pgp的信息了

这个公钥验证的光盘的来源,如果是通过epel获取的rpm包,则需要到epel的官方站点上获取公钥。