1.2 RPM软件包基础知识
有了.tgz、.rar或者.zip格式的软件包,日常学习和工作就够用了吗?对于某些小型应用来说,这样确实能满足需求了。然而,在工作中往往会碰到如下一些需求,使得我们不能满足于停留在这个层面的软件包上:
- 查看某个软件包的安装时间、制作人、制作时间、描述信息等。
- 使软件包具备一些特殊功能,比如,除了文件复制外,还要能生成配置文件,并且能提供安装服务、执行命令等。
- 当软件版本升级时,通过压缩文件重新覆盖的做法在文件很大时显然是不可行的,此时就会希望使数据量更新达到最小。
除了以上3点,可能还有其他方面的问题,相信读者或多或少都遇到并思考过。那么,是否存在某个格式的软件包,这种软件包能在文件压缩存储之外再支持更多的功能呢?答案是肯定的,这就是我们要介绍的RPM软件包。
1.2.1 RPM软件包的功能
RPM就是能够解决上面提到的问题的若干种软件包中的一类。当然还有其他格式的软件包也能解决这些问题,不过本书只对RedHat系统上的RPM进行讨论。
RPM软件包的功能如下:
- 存储数据压缩。
- 文件安装。
- 配置文件生成。
- 系统服务注册。
- 软件依赖检查。
除了前两个功能外,其他3个功能是一般的压缩格式软件包都不具备的。下面详细介绍RPM的这几个功能。
1.存储数据压缩
RPM具有软件包的基本功能—数据压缩存储,它支持常见的bz2和gzip等压缩算法。RPM安装列表中的所有文件在按照某个指定的算法(默认是gzip)压缩后,作为最终RPM文件的一个数据块,与其他控制信息存储进同一个文件中。最终所有的数据都存储在同一个RPM文件中。
读者可以在制作RPM前先计算一下安装包的大小,生成RPM后,再计算一下RPM文件的大小,两者一比较就能得到RPM的压缩效果了。比如笔者开发的一个测试包,安装目录大小为5.2MB,而该目录生成的RPM文件却只有2.4MB。
2.文件安装
文件安装是软件包的一个基本功能,比如我们运行如下命令:
rpm-qpl ./cmeguard-1.1.2-34.i386.rpm
输出内容如下:
/etc/init.d/cmeguard /usr/local/cmeguard/bin/cmesync /usr/local/cmeguard/bin/daemon /usr/local/cmeguard/bin/genfinger /usr/local/cmeguard/bin/run /usr/local/cmeguard/bin/sync_plug /usr/local/cmeguard/conf/cmeguard.conf
这里输出的所有文件,最终都会在软件包安装时被安装到目标操作系统上,在使用以下默认选项安装这个包之后,就可以在系统上找到以上列表中所有的文件了。
rpm-ivh cmeguard-1.1.2-34.i386.rpm
一般情况下,被安装的文件不仅仅是这里能看到的文件(事实上,更多的文件可能被安装了),因为RPM除了会安装文件列表中指定的文件外,还会在安装过程中动态生成一些文件,并且安装到系统中。具体介绍参见后面章节。
3.配置文件生成
配置文件既可以指定为安装列表中的文件,也可以通过安装过程中运行的脚本来生成。如果是静态文件,直接加入安装目录中,通过文件列表的方式来安装;如果配置文件的内容和所安装的系统的运行时信息相关,那么就需要在安装过程中来动态生成了。例如,本书后面提供的名为repoutils的软件包,在生成以下配置文件时,就是根据操作系统的版本信息和平台信息来动态生成文件中的baseurl项的内容的。
/etc/yum.repos.d/redhat.repo
4.系统服务注册
如果你曾使用rpm命令安装过一些软件包,比如常见的apache、mysql-server等,应该会知道,在安装完成后,目录/etc/init.d/下会生成一个httpd或者mysqld文件。这个文件是按照标准的Linux服务脚本的格式编写的(参考chkconfig的文档)。当系统以对应的模式启动时(参考Linux run levels文档),之前安装的服务程序就会被启动运行,因为/etc/init.d目录下的每一个文件都会被系统识别为一个服务控制命令,系统在启动过程中,会向每个安装命令(比如httpd)传递一个start参数来执行该命令,从而触发该服务(httpd)的启动,关机过程中对服务的停止也是类似的。
举个例子,运行以下命令:
rpm -qpl ./vsftpd-2.0.5-10.el5.i386.rpm | grep init
输出如下:
/etc/rc.d/init.d/vsftpd
说明RPM包中的这个文件默认会被安装到系统的如下位置。
/etc/rc.d/init.d/vsftpd
安装完成后,可以通过以下命令来启动vsftpd服务。
service vsftpd start
通过以下命令来停止vsftpd服务。
service vsftpd stop
通过以下命令来重启vsftpd服务。
service vsftpd restart
或者通过以下命令来查看这个服务的运行状态。
service vsftpd status
5.软件依赖检查
在工作中,我们开发的程序很少单独就能运行,大多数程序都会依赖其他组件。比如,数据库操作程序可能需要libmysql的支持,网络报文处理程序或许需要libpcap库的支持。
为了保证每个软件在安装后都能正常运行,在安装之前或者安装过程中,软件安装程序需要对该软件包所依赖的所有元素进行检查。而这种检查机制,就可以通过RPM的require等语法来实现(参见第2章关于SPEC文件的内容)。例如,有个RPM文件,其文件名称为test_rpm-1.1.1-21.i386.rpm,查看该包所依赖(require)的服务或者组件的命令如下:
rpm-qp test_rpm-1.1.1-21.i386.rpm –requires
输出如下:
test__require_pkg ruby-libs /bin/sh /bin/sh rpmlib(PayloadFilesHavePrefix)<= 4.0-1 rpmlib(CompressedFileNames)<= 3.0.4-1
上面的输出内容就是test_pm这个包在安装时所依赖的所有元素。然后尝试如下安装命令:
rpm-ivh test_rpm-1.1.1-21.i386.rpm
能够看到如下输出:
error:Failed dependencies: test__require_pkg is needed by test_rpm-1.1.1-21.i386
我们发现,由于系统缺少test__requre_pkg这个软件包(或者虚拟包),从而导致test_rpm-1.1.1-21.i386.rpm的安装失败。另外,执行如下命令来查看ruby-libs这个包的安装情况:
rpm-qa ruby-libs
输出如下:
ruby-libs-1.8.5-5.el5_3.7
从中能够看到,虽然test-rpm所依赖的ruby-libs软件包已经安装了,但是test-rpm还是不能安装,这是因为,在一个软件包的依赖列表中(test__require_pkg和ruby-libs),所有依赖组件都是“与”的关系,也就是说,缺少任何一个依赖组件(test__require_pkg),目标RPM都不能安装。
1.2.2 RPM实现引子
为了引出后面章节的内容,我们在这里对1.2节开始部分提的问题进行简单解答。
RPM是怎样在压缩存储之外又实现其他功能的呢?比如:安装服务、执行命令、打印信息、发邮件、检查依赖包,还有升级时做版本检查等功能。
关于这些功能的实现,在此只做简单介绍,细节留待有关SPEC的章节再作说明。
阅读后面的章节我们会了解到,RPM有个功能就是对嵌入脚本的支持:它支持在安装软件或者卸载软件的过程中(确切地说,是这个过程的开始、进行时和结束后这几个不同的动作点),执行用户指定的命令。常用的命令执行点如下:
- pre install
- post install
- pre uninstall
- post uninstall
从字面就能看到每个执行点的含义:pre/post install表示在安装之前或者之后;pre/post uninstall表示在卸载之前或者之后。
这种支持执行自定义嵌入脚本的机制,为扩展软件包的功能提供了很大的空间。
再来看一个例子,执行如下命令来查看指定RPM中嵌入的脚本:
rpm-qp test_rpm-1.1.1-21.i386.rpm –scripts
输出如下:
preinstall scriptlet (using/bin/sh): echo "pre install scripts by duanjigang" postinstall scriptlet (using/bin/sh): echo "post install scripts by duanjigang" preuninstall scriptlet (using/bin/sh): #!/bin/bash echo "pre uninstall by duanjigang" postuninstall scriptlet (using/bin/sh): #!/bin/bash echo "post uninstall by duanjigang"
从输出情况能够看到,这个软件包嵌入了4个脚本,分别在安装前后和卸载前后执行,这样,使用者就可以通过这些脚本来实现自己想要的功能了。
关于scripts(脚本)在哪些动作点执行时会有什么效果,在后面会详细说明。
另外一个问题:RPM是怎样实现版本升级的?
执行如下命令查看RPM包的信息:
rpm-qpi test_rpm-1.1.1-21.i386.rpm
可以查看到该RPM包的信息如下:
Name :test_rpm Version :1.1.1 Release :21
我们看到,test-rpm的Version是1.1.1,Release是21,因此它默认的包名如下:
test_rpm-1.1.1-21
在对version或release进行升级后,新生成的RPM就可以用来升级老版本的安装包了。rpm命令会自动检查待安装包和已安装软件包的信息,确认待安装包是否能升级已安装软件包。软件的升级是一个复杂的过程,必须谨慎地考虑每一个步骤,保证升级时所做的一切操作尽可能少地影响已经安装软件的正常运行,只有这样才能完成新版本软件的安装。
RPM的基础知识就先介绍到这里。