一 介绍
RPM(RPM Package Manager)是一个开放的包管理器,它使用户可以从源码构建一个二进制的软件发行包和利用补丁包给软件打补丁。RPM包非常灵活易用,因此被作为很多linux发行版的默认软件安装包。在Redhat和CentOS中都是使用此打包格式。
二 制作
1 创建一个RPM安装包是件很容易的事,特别是当你可以获得软件的源代码包的时候。下面介绍怎么制做一个RPM软件安装包,在继续之前,我们假设你已经知道怎么从源代码安装一个软件包。制做一个RPM软件安装包有以下几个步骤:
(1)获得软件的源代码包
(2)如果你自己修改了软件,那么给它做一个补丁
(3)编写一个包含软件包信息的spec文件
(4)确保软件被正确的安装到适当的位置
(5)创建RPM安装包
2 从上面的几步我们可以看到,制做一个RPM包最主要的就是第三步编写一个spec文件,下面介绍怎么编写这个spec文件。一个spec文件分成下面几个小节:
(1)前言(preamble)
当用户查询软件包信息的时候,RPM程序会打印出前言包含的信息。这一小节包含的信息有软件包的名称、功能描述、版本号、发行号和类型等信息。
(2)准备(preparation)
从prep节开始是创建一个软件包要做的实际工作。故名思意,这一小节所做的都是一些必须的准备工作,它的内容就像一个普通的shell脚,为了使工作更容易,这一小节提供了两个可以使用的宏,一个是解压tar文件,并把当前工作目录设置为源代码目录,另一个是给源码打补丁。
(3)创建(build)
就像prep小节一样,build的内容也是一个普通脚本,这一小节包含的是怎么编译源代码,它可以是一个简单的make命令或者一些更复杂的编译命令。因为现在的大多数软件都使用make编译,所以这一小节没有提供宏。
(4)安装(install)
install小节同样也是一个脚本,它提供一些安装软件包的命令,如果源代码的makefile文件提供有make install命令,这一节你可以简单的包含一个make install命令,否则你就得提供一些像cp, mv或者install之类的命令集。
(5)验证(verify script)
这一小节包含一个验证软件包的脚本,验证软件包不属于RPM的能力范围。
(6)清除(clean)
这一小节包含一个编译好以后用于清除无用信息的脚本。这一脚本很少会用到,因为在大多数环境下,RPM会做好这些工作。
(7)文件列表(file list)
这一小节包含一份文件列表,它们是组成RPM包的所有文件,当你用rpm -qpl 命令查看软件包的时候就会得到这一份文件列表。在这一小节也有几个宏可以用,它们指出哪些文件是文档,哪些是配置文件,哪里是目录等。
(8)维护日志(changelog)
这一小节记录了软件包的维护日志。
3 spec文件有一个命名规则,其文件名由以下几部份组成:软件包名-版本号-发行号.spec
4 下面我们举一个简单的spec文件,然后再来说明各部分的意思。文件如下:
Summary: GNU readline library
Name: readline
Version: 5.1
Release: 1
Copyright: GPL
Group: Library
Source: http://www.cnblogs.com/itech/admin/ftp://172.16.100.81/soft/readline-5.1.tar.gz
URL: http://www.gnu.org/index.html
Distribution: GNU Project
Vendor: GNU
Packager: Yan Dingcheng <dingcheng_yan@yahoo.com.cn>
%description
The GNU readline library gets a line from user with editing.
%prep
%setup
%build
./configure --prefix=/opt/%{name}
make
%install
make install
%files
/opt/%{name}/lib/libhistory.a
/opt/%{name}/lib/libhistory.so
/opt/%{name}/lib/libhistory.so.5
/opt/%{name}/lib/libhistory.so.5.1
/opt/%{name}/lib/libreadline.a
/opt/%{name}/lib/libreadline.so
/opt/%{name}/lib/libreadline.so.5
/opt/%{name}/lib/libreadline.so.5.1
/opt/%{name}/include/readline/chardefs.h
/opt/%{name}/include/readline/history.h
/opt/%{name}/include/readline/keymaps.h
/opt/%{name}/include/readline/readline.h
/opt/%{name}/include/readline/rlconf.h
/opt/%{name}/include/readline/rlstdc.h
/opt/%{name}/include/readline/rltypedefs.h
/opt/%{name}/include/readline/tilde.h
/opt/%{name}/info/dir
/opt/%{name}/info/history.info
/opt/%{name}/info/readline.info
/opt/%{name}/info/rluserman.info
/opt/%{name}/man/man3/history.3
/opt/%{name}/man/man3/readline.3
%changelog
* Wed Jan 31 2007 <dingcheng_yan@yahoo.com.cn>
+ create package
5 SPEC实例文件的具体解释:
前言
Summary:这一行文字对软件包进行简短描述
Name:软件包的名字
Version:软件包的版本号,这里必须是你计划要使用的RPM文件版本号
Release:软件包的发行号,这里必须是你计划要使用的RPM文件发行号
Copyright:软件包的版权
Group:软件包的分组,这里定义怎么打包软件包
Source:软件包的来源,当你想再次获取该软件包或者查看它是不是有更新的版本的时候,这一行就很有用了。
URL:URL与Source不一样的地方就是,Source提供的是源代码的文件名,URL提供的是指向软件包文档的链接。
Distribution:指明软件包是属于哪个产品的一部份。
Vendor:软件包的生产厂商。
Packager:打包的组织或者个人。
discription:软件包功能的一个详细描述。
准备
%setup宏:解压源代码包并把当前工作目录设置到源代码目录。%setup宏做的主要工作类似于下面两条命令:
tar zxvf 源代码包文件名
cd RPM包名-版本号
所以如果你的源代码包解压以后的目录组成不是“RPM包名-版本号”的话,在这里使用%setup宏就会出问题。
创建
这里使用了一个configure和make命令组合
安装
这里使用了make install命令,因为makefile里有install标签了,所以就用它,简便。
文件列表
这里是一个文件列表,列出的文件就是创建以后的RPM包将要包含的文件,文件路径要求是一个绝对路径,利用RPM命令安装这个软件包以后,这些文件将会按照这里指定的路径安装到系统中。在创建RPM包之前必须保证这里指定的文件在系统中都能找到,不然创建RPM包将会出错。所以如果是为了学习怎么编写一个spec文件的话,就像我上面那样,把软件安装到一个干净目录下(比如/opt),这样不会影响系统的正常工作。
这个文件列表目前还没有什么好的工具能够自动生成,因为RPM没法知道执行make install的时候到底安装了哪些文件。有的人建议用一个find命令来查找到底安装了哪些文件,但是我觉得这未必会有用。我一般是在configure的时候使用configure --prefix=/opt/package_name指定一个干净目录,先把软件安装到该目录下,然后查看软件包安装后都有哪些文件,通过这些文件生成一个文件列表,然后再使用configure命令重新安装一次软件包,这次把软件包安装到系统中,比如是/usr或者/usr/local目录下,然后把文件列表中的目录前辍改成相应的目录前辍(比如/usr或者/usr/local)就可以了。
维护日志
维护日志是一些对软件包维护的日志记录,其中包含有一个时间信息,它有指定的格式:Wed Jan 31 2007。按顺序是 星期 月 日 年。
6 生成rpm安装包:
编写好spec文件以后在redhat linux下把软件源码包放到/usr/src/redhat/SOURCE目录下(如果是suse linux把软件源码包放到/usr/src/packages/SOURCE目录下),
然后把spec文件放到/usr/src/redhat/SPECS目录下(如果是suse linux放到/usr/src/packages/SPECS目录下),
最后转到/usr/src/redhat/SPECS目录下执行如下命令:rpmbuild -ba spec文件名 。
执行成功以后会生成三个RPM文件并打印信息如下:Wrote: /usr/src/redhat/SRPMS/readline-5.1-1.src.rpm,Wrote: /usr/src/redhat/RPMS/i386/readline-5.1-1.i386.rpm,Wrote: /usr/src/redhat/RPMS/i386/readline-debuginfo-5.1-1.i386.rpm。
我们可以看到在RedHat系统下生成的RPM文件被放到/usr/src/redhat/RPMS/i386和/usr/src/redhat/SRPMS目录下,如果打包的RPM包是为了i586架构打的,那么RPM包会被放到i586目录下。其中readline-5.1-1.src.rpm是源码包,可以通过命令 rpmbuild --rebuild readline-5.1-1.src.rpm重新生成二进制的RPM包。
三 使用
1 rpm -i (安装)
在第一次安装某个包时,您要使用 -i 或安装模式。只需将 rpm 指向某个二进制包并执行它, rpm 就会把该包安装到您的系统上。安装过程一般只需几秒钟。我经常会在安装包时使用 -v (详细)开关来提供关于该过程的更多信息,以及使用 -h (哈希线)开关来通过输出在控制台上的哈希(#)符号提供安装进度更新。下面是安装某个包的例子:
$ rpm -ivh MyPackage-1.0.0.i386.rpm
Preparing... ########################################### [100%]
1:MyPackage ########################################### [100%]
就是这个样子!MyPackage 现在已经安装完成,可供使用了。
2 rpm -e (删除)
要删除已安装的包,可使用 -e 开关。 rpm 将使用数据库来删除该包的所有文件。如果有已安装的其他包依赖正在删除的包, rpm 将会异常退出。您必须使用 nodeps 开关来执行强制删除( nodeps 还可以用于强制安装)。在使用这个开关来强制安装或删除时,务必 非常 小心。删除其他包所依赖的包,可能会导致灾难性的结果。下面这个命令删除我们在上面安装的包:
$ rpm -e MyPackage
注意,包的删除并不一定需要它的完整名称(包括版本号)。安装时需要完整名称,因为我们是在引用一个文件名称。已安装的包仅通过它们的名称来引用。包的名称是版本号之前的所有内容。
3 rpm -V(验证)
验证开关非常有用。它将包文件的当前状态与它们在安装时的原始状态作比较。两种状态之间的区别将用一个代码来显示:
文件验证结果
S
文件大小不一致
M
模式不一致(包括权限和文件类型)
5
MD5 校验和不一致
D
设备主要/次要编号不匹配
L
readLink(2) 路径不匹配
U
用户拥有关系不一致
G
群组拥有关系不一致
T
mTime 不一致
如果您对某个包运行 rpm -V ,并且发现某个可执行文件的大小发生了变化,那可能就是安全漏洞的征兆。
4 rpm -U(升级)
一旦某个包已经安装,尝试安装具有相同名称的包将产生一条消息,指出该包已经安装。 如果想要将某个包升级到更新的版本,可使用 -U 开关来升级。升级还具有另一个影响。当对多个包名称运行升级时,它将设法按依赖关系的顺序放置包。换句话说,必需的包将首先安装。不管某个包是否已经安装,都可以对它使用升级开关,许多人使用它而不是使用 -i 开关来执行安装和升级。下面是使用升级开关来加载多个 rpm 包的例子:
$ rpm -Uvh My*.rpm
Preparing... ########################################### [100%]
1:bMyPackageDep ########################################### [ 50%]
1:aMyPackageNew ########################################### [100%]
在上面的例子中,bMyPackageDep 是 aMyPackageNew 的前提条件,因此尽管文件名称以相反的顺序排列, rpm 也会对它们正确排序。
5 rpm -q(查询)
可以从 rpm 数据库中查询多种有用的信息。对 rpm 数据库拥有读访问权限的任何用户都能够运行查询。默认情况下,全部用户都拥有读访问权限。要运行一个查询,可使用 -q 开关带上要查询的包的名称。这样将返回该包的版本。
$ rpm -q MyPackage
MyPackage-1.0.0
包的名称必须精确匹配,不允许使用通配符。然而,如果记不住包的完整名称,您可以使用 grep 工具来帮助找到它。可以使用 -qa 开关来查询所有已安装的包,并用 grep 来管道输出您能记住的信息。例如:
$ rpm -qa | grep IBM
IBMWSAppDev-Product-5.0-0
IBMWSSiteDevExp-Core-5.0-0
IBMWSSiteDev-Core-5.0-0
IBMWSTools-WAS-BASE-V5-5.0-0
IBMJava118-SDK-1.1.8-5.0
IBMWSWB-samples-5.0-0
IBMWSWB-5.0-0
IBMWSAppDev-Core-5.0-0
IBMWSAppDev-5.0-0
IBMWSTools-5.0-0
除了版本号外, rpm -q 还可以提供关于包的其他有用信息。下面就是这样一些例子:
使用 rpm 查询获取信息
rpm -q changelog
显示包的开发变更历史记录
rpm -qc
显示包的配置文件
rpm -qd
显示包的文档文件
rpm -qi
显示包描述
rpm -ql
显示包的文件的列表
rpm -qR
显示包的依赖关系
还有另一个有趣的查询命令,它针对文件而不是针对包运行。
rpm -q whatprovides <filename>
上面这个命令将识别与给定的 filename(文件名)相关联的包。filename 必须包括文件的绝对路径,因为信息就是以这种方式存储在 rpm 数据库中的。
四 参考
1)http://hi.baidu.com/imace/blog/item/767c992677601c148b82a111.html
2)http://www.ibm.com/developerworks/cn/linux/l-roadmap/part9/index.html
五 完!