现有RPM包:abcd.rpm
查询: # rpm -qa | grep abcd
安装: # rpm -ivh abcd.rpm
卸载: # rpm -e abcd
RPM命令大全
2004-04-23 15:18 pm
作者:作者
来自:无名
一、安装
命令格式:
rpm -i ( or --install) options file1.rpm ... fileN.rpm
参数:
file1.rpm ... fileN.rpm 将要安装的RPM包的文件名
详细选项:
-h (or --hash) 安装时输出hash记号 (``#'')
--test 只对安装进行测试,并不实际安装。
--percent 以百分比的形式输出安装的进度。
--excludedocs 不安装软件包中的文档文件
--includedocs 安装文档
--replacepkgs 强制重新安装已经安装的软件包
--replacefiles 替换属于其它软件包的文件
--force 忽略软件包及文件的冲突
--noscripts 不运行预安装和后安装脚本
--prefix <path> 将软件包安装到由 <path> 指定的路径下
--ignorearch 不校验软件包的结构
--ignoreos 不检查软件包运行的操作系统
--nodeps 不检查依赖性关系
--ftpproxy <host> 用 <host> 作为 FTP代理
--ftpport <port> 指定FTP的端口号为 <port>
通用选项
-v 显示附加信息
-vv 显示调试信息
--root <path> 让RPM将<path>指定的路径做为"根目录",这样预安装程序和后安装程序都会安装到这个目录下
--rcfile <rcfile> 设置rpmrc文件为 <rcfile>
--dbpath <path> 设置RPM 资料库存所在的路径为 <path>
二、删除
命令格式:
rpm -e ( or --erase) options pkg1 ... pkgN
参数
pkg1 ... pkgN :要删除的软件包
详细选项
--test 只执行删除的测试
--noscripts 不运行预安装和后安装脚本程序
--nodeps 不检查依赖性
通用选项
-vv 显示调试信息
--root <path> 让RPM将<path>指定的路径做为"根目录",这样预安装程序和后安装程序都会安装到这个目录下
--rcfile <rcfile> 设置rpmrc文件为 <rcfile>
--dbpath <path> 设置RPM 资料库存所在的路径为 <path>
三、升级
命令格式
rpm -U ( or --upgrade) options file1.rpm ... fileN.rpm
参数
file1.rpm ... fileN.rpm 软件包的名字
详细选项
-h (or --hash) 安装时输出hash记号 (``#'')
--oldpackage 允许"升级"到一个老版本
--test 只进行升级测试
--excludedocs 不安装软件包中的文档文件
--includedocs 安装文档
--replacepkgs 强制重新安装已经安装的软件包
--replacefiles 替换属于其它软件包的文件
--force 忽略软件包及文件的冲突
--percent 以百分比的形式输出安装的进度。
--noscripts 不运行预安装和后安装脚本
--prefix <path> 将软件包安装到由 <path> 指定的路径下
--ignorearch 不校验软件包的结构
--ignoreos 不检查软件包运行的操作系统
--nodeps 不检查依赖性关系
--ftpproxy <host> 用 <host> 作为 FTP代理
--ftpport <port> 指定FTP的端口号为 <port>
通用选项
-v 显示附加信息
-vv 显示调试信息
--root <path> 让RPM将<path>指定的路径做为"根目录",这样预安装程序和后安装程序都会安装到这个目录下
--rcfile <rcfile> 设置rpmrc文件为 <rcfile>
--dbpath <path> 设置RPM 资料库存所在的路径为 <path>
四、查询
命令格式:
rpm -q ( or --query) options
参数:
pkg1 ... pkgN :查询已安装的软件包
详细选项
-p <file>(or ``-'') 查询软件包的文件
-f <file> 查询<file>属于哪个软件包
-a 查询所有安装的软件包
--whatprovides <x> 查询提供了 <x>功能的软件包
-g <group> 查询属于<group> 组的软件包
--whatrequires <x> 查询所有需要 <x> 功能的软件包
信息选项
<null> 显示软件包的全部标识
-i 显示软件包的概要信息
-l 显示软件包中的文件列表
-c 显示配置文件列表
-d 显示文档文件列表
-s 显示软件包中文件列表并显示每个文件的状态
--scripts 显示安装、卸载、校验脚本
--queryformat (or --qf) 以用户指定的方式显示查询信息
--dump 显示每个文件的所有已校验信息
--provides 显示软件包提供的功能
--requires (or -R) 显示软件包所需的功能
通用选项
-v 显示附加信息
-vv 显示调试信息
--root <path> 让RPM将<path>指定的路径做为"根目录",这样预安装程序和后安装程序都会安装到这个目录下
--rcfile <rcfile> 设置rpmrc文件为 <rcfile>
--dbpath <path> 设置RPM 资料库存所在的路径为 <path>
五、校验已安装的软件包
命令格式:
rpm -V ( or --verify, or -y) options
参数
pkg1 ... pkgN 将要校验的软件包名
软件包选项
-p <file> Verify against package file <file>
-f <file> 校验<file>所属的软件包
-a Verify 校验所有的软件包
-g <group> 校验所有属于组 <group> 的软件包
详细选项
--noscripts 不运行校验脚本
--nodeps 不校验依赖性
--nofiles 不校验文件属性
通用选项
-v 显示附加信息
-vv 显示调试信息
--root <path> 让RPM将<path>指定的路径做为"根目录",这样预安装程序和后安装程序都会安装到这个目录下
--rcfile <rcfile> 设置rpmrc文件为 <rcfile>
--dbpath <path> 设置RPM 资料库存所在的路径为 <path>
六、校验软件包中的文件
语法:
rpm -K ( or --checksig) options file1.rpm ... fileN.rpm
参数:
file1.rpm ... fileN.rpm 软件包的文件名
Checksig--详细选项
--nopgp 不校验PGP签名
通用选项
-v 显示附加信息
-vv 显示调试信息
--rcfile <rcfile> 设置rpmrc文件为 <rcfile>
七、其它RPM选项
--rebuilddb 重建RPM资料库
--initdb 创建一个新的RPM资料库
--quiet 尽可能的减少输出
--help 显示帮助文件
--version 显示RPM的当前版本
制作篇(上)
要想制作一个RPM格式的软件包,需要编写软件包描述文件。其标准命名格式为:软件名-版
本号-释出号.spec,这个文件,详细描述了有关该软件包的诸多信息,如软件名,版本,类别, 说
明摘要,创建时要执行什么指令,安装时要执行什么操作,以及软件包所要包含的文件等等。 有
了这个文件,RPM就可以制作出相应的包裹文件来。
下面以我制作小赵编辑器LZE的软件包(lze-6.0-2.i386.rpm)为例,详细说明一下软件包描
述文件的书写。其描述文件为lze-6.0-2.spec,该文件内容如下:(用nl -ba命令列出,每行开头
的数字为所在行在文件中的行号)
1 # 文件名称: lze-6.0-2.spec
2 # 文件功能: lze软件包描述信息
3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利
4 # 修改时间: 2001.10.19
5
6 Name: lze
7 Version: 6.0
8 Release: 2
9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用)
10 Group: Applications/Editors
11 License: Share
12 Vendor: 纵横软件制作中心
13 Packager: 雨亦奇(zhsoft@371.net)
14 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz
15 Prefix: /usr
16 Requires: /bin/sh
17 Provides: lze-edit
18
19 %description
20 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗
21 口中英文多功能编辑器。
22 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十
23 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特
24 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎
25 添翼。10.即时翻译,按到即译。
26 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。
27 它将在工作中助您一臂之力,轻松上阵,游刃有余!
28
29 %prep
30 echo "预处理脚本程序(prep)开始执行"
31 %setup
32
33 %build
34 echo "编译连接脚本程序(build)开始执行"
35 make
36
37 %install
38 echo "安装脚本程序(install)开始执行"
39 make install
40
41 %clean
42 echo "建包结束后清理脚本程序(clean)开始执行"
43
44 %pre
45 echo "安装前执行脚本程序(pre)开始执行"
46
47 %post
48 echo "安装后执行脚本程序(post)开始执行"
49
50 %preun
51 echo "卸载前执行脚本程序(preun)开始执行"
52
53 %postun
54 echo "卸载后执行脚本程序(postun)开始执行"
55
56 %veryfiscript
57 echo "软件包校验脚本程序(verifyscript)开始执行"
58
59 %triggerin -- xiuwu
60 echo "软件包安装时触发脚本程序(triggerin)开始执行"
61
62 %triggerun -- yuntaishan < 2.0
63 echo "软件包卸载前触发脚本程序(triggerun)开始执行"
64
65 %triggerpostun -- dapubu
66 echo "软件包卸载后触发脚本程序(triggerpostun)开始执行"
67
68 %files
69 %defattr (-,root,root)
70 %config /etc/funkey.def
71 %config /etc/inputme.def
72 %doc /usr/doc/lze-6.0/README
73 %doc /usr/doc/lze-6.0/LICENSE
74 /usr/bin/lze
75 /usr/bin/lzeime.py
76 /usr/bin/lzeime.wb
77 /etc/wbzc.dat
78
79 %changelog
80 * Tue Aug 18 1998 雨亦奇
81 - 内置拼音,五笔输入法
82 * Fri May 01 1998 雨亦奇
83 - 增加多窗口操作
84 * Mon Mar 24 1997 雨亦奇
85 - 增加块操作命令
86
该描述文件包括以下几方面的内容:
一、注释行
见第1-4行。
它以#号开头,起注解作用,可帮助用户理解所写的内容,但对软件包的生成不起任何作用。
此文件中,注释行集中在文件首部。实际上,它可位于描述文件的任何位置。
二、文件头
见第6-17行。
文件头描述软件包的基本信息,它包含若干个域,其中有必选的域,也有可选的域。一个域占用一行,其描述格式为:
域名 : 域值
注意: 域名不分大小写,并且域值不能为空。
文件头必选域有以下六个:
1. Name :
此域定义软件名。
2. Version :
此域定义版本号。仅当软件较以前有较大改变时才增加版本号。注: 版本号中不能含减号(-)字符。
3. Release :
此域定义释出号。若软件较以前改变较小,则仅增加释出号,不改变版本号。注: 释出号中亦不能含减号(-)字符。
RPM利用上述的Name(软件名),Version(版本号),Release(释出号)及体系号来命名软件包,如本例输出的包裹文件名为lze-6.0-2.i386.rpm。
4. Summary :
此域定义软件包简介,为一句话说明。
5. Group :
此域定义软件所属类别,详见<<精通RPM之五--查询篇>>,本例的Applications/Editors表示本软件属"应用/编辑器"类。
6. License :
此域定义软件适用的许可证或版权规则。该域也可用Copyright(版权)来定义,二者同意。许可证具体有: GPL(通用公共许可证,自由软件适用),BSD,MIT,Public Domain(公共域),Distributable(贡献),Commercial(商业),Share(共享)等。
文件头可选的域包括如下几类:
1. 基本信息
1.1 Vendor :
此域定义软件的供应商(销售商)。
1.2 Distribution :
此域定义软件所属的发行版,这是软件包制作者自己的分类。通常,一个发行版由若干个软件包构成。如我想做一个名为“熊猫'95”的发行版,则其中每个软件包(如竹叶95)的描述文件都应有这么一行:
Distribution : 熊猫'95
1.3 Icon :
此域指定软件包所用的图标文件名。此文件为GIF或XPM格式,必须存放在RPM的%_sourcedir
(源码目录)宏所指示目录下,默认为/usr/src/dist/SOURCES。RPM本身并不使用图标,但它
将图标文件内容存贮到包裹文件中,安装时亦存贮到RPM数据库中。此图标可被图形界面的
RPM包管理工具使用,用以改善界面效果,增加可视性。如下例指示软件包使用panda.xpm作
为图标:
Icon : panda.xpm
1.4 Packager :
此域定义打包者,亦即建立此软件包的人或公司。书写格式是:
打包者的名字 <电子信箱或相关网页>
请参考描述文件第13行。
1.5 Serial :
此域定义软件序列号,也可使用域名Epoch。软件序列号为一整数,由打包者指定,它应随着版本号的增加而不断增加,并且始终保持数值的唯一。软件序列号可被用来说明软件包之间的依赖关系。下例指定软件包序列号为4:
Serial : 4
或用:
Epoch : 4
1.6 URL :
此域定义包含打包软件有关信息的网页地址。如:
URL : http://devplanet.fastethernet.net/gxedit.html
2. 依赖相关
依赖是RPM用来描述软件包之间关系的。一个软件包依赖的东西RPM称作功能,它可以是真实存在的软件包,也可以是虚拟的软件包(虚包)。虚包没有版本号。
依赖相关的域有:
2.1 Provides :
此域定义软件包提供的功能,可重复多行。其描述格式为:
Provides : 功能1 [,功能2] ...
注: []所括为可选项,多个功能之间以逗号或空格分隔。
软件包所提供的功能一般是以虚包形式存在的共享库。当有多个软件包均提供相同的服务时,常用虚包来表示其服务。如,一个邮件客户端软件允许用户使 用不同的看信方式(文本形式,HTML形式等),可以要求任何一个看信程序必须提供mail-reader虚包。这样,看信程序的描述文件应有这么一行:
Provides : mail-reader
如此它才能被邮件客户端使用。
2.2 Requires :
此域定义软件包所需的功能,可重复多行。其描述格式为:
Requires : 功能1 [比较符1 [序列号1:]版本号1[-释出号1]] [,功能2 [比较符2 [序列号2:]版本号2[-释出号2]]] ...
其中: * []所括为可选项;
* 比较符可使用<(小于),>(大于),=(等于),>=(大于等于)或<=(小于等于);
* 序列号不选时,RPM默认为0;
* 功能之间的逗号可选,也可使用空格进行分隔。
例子:Requires: aaa, bbb >= 3.0, ccc < 2:5.0-1
注: 本例定义生成的包在安装时需要系统有如下功能:
(1) aaa(系统中已安装aaa包,或者已安装软件包中有软件包提供aaa虚包);
(2) bbb包已安装且版本要求大于等于3.0;
(3) ccc包已安装且版本要求小于序列号为2,版本号为5.0且释出号为1。
RPM在进行版本比较时,执行比较的顺序是; 先版本号,再释出号,最后比较序列号。通过比较,确定哪个版本较新,哪个版本较老。
2.3 Conflicts :
此域定义有哪些功能与本软件包相冲突(不能共存)。此域亦可在描述文件中书写多次。其描述格式形同Requires域,为:
Conflicts : 功能1 [比较符1 [序列号1:]版本号1[-释出号1]] [,功能2 [比较符2 [序列号2:]版本号2[-释出号2]]] ...
其中: * []所括为可选项;
* 比较符可使用<(小于),>(大于),=(等于),>=(大于等于)或<=(小于等于);
* 序列号不选时,RPM默认为0;
* 功能之间的逗号可选,也可使用空格进行分隔。
举个例子:
Conflicts : xxx=1:2.0 yyy>=3.0
注: 本例阐明生成的包冲突的功能有:
(1) 当系统中xxx包版本等于序列号为1且版本号为2.0时;(2) 当系统中yyy包版本大于等于3.0时。
*** 依赖关系的自动实现 ***
一般情况下,当RPM建立一个软件包时,它要执行/usr/lib/rpm目录下的两个小程序。一个是find-requires,用于查找软件 包所需的共享库,这些库将以虚包的形式加入到该软件包所需的功能(Requires)之中。另一个是find-provides,它用于查找软件包所提供 的共享库,这些库将以虚包的形式加入到该软件包所提供的功能(Provides)之中。这两个程序都是SHELL程序,代码量虽小,但确实帮了软件包制作 者一个大忙--不必劳心费神地自己写这样的依赖关系了,因为程序均自动完成了。
下面三个域用于指示RPM是否执行这两个程序。
2.4 Autoreq :
此域用于指示RPM是否自动查找软件所需的共享库。仅当域值为no或0时,RPM不执行find-requires程序,否则均执行该程序。
2.5 Autoprov :
此域用于指示RPM是否自动查找软件提供的共享库。仅当域值为no或0时,RPM不执行find-provides程序,否则均执行该程序。
2.6 Autoreqprov :
此域用于指示RPM是否自动查找软件所需的共享库与其提供的共享库。仅当域值为no
或0时,RPM不执行find-requires与find-provides两个程序。此域相当于同时设定Autoreq
与Autoprov域值为指定之值。
注: 上述三个域在描述文件中,它们之间因为顺序的不同而结果会有所不同,一般以最后一个为准。如:
Autoreq : yes
Autoreqprov : no
Autoprov : yes
注: 本例虽然第一行允许执行find-requires,但第二行又不允许find-requires与find-provides两个程序运行,而第三行允 许find-provides运行,所以依照执行顺序,结果为不允许执行find-requires,而允许执行find-provides。
又如:
Autoreq : no
Autoreqprov : yes
Autoprov : no
注: 本例的结果为允许执行find-requires,而不允许执行find-provides。
3. 系统相关
RPM制作软件包时,可以为其指定适用的CPU体系或操作系统,也可为其指定不适用的CPU体系或操作系统,这样,当RPM发现当前的CPU体系 或操作系统与软件包要求的不兼容时,将中止软件包的制作。RPM默认的当前CPU体系由宏%_arch定义,一般为i386。RPM默认的当前操作系统由 宏%_os定义,一般为linux。读者可以通过查看/usr/lib/rpm/macros宏定义文件得到。
下面四个域说明软件包的适用范围:
3.1 Excludearch :
此域定义软件包不适用的体系。RPM可选的体系名请参见/usr/lib/rpm/rpmrc文件中的arch_canon项目。
软件包不适用于某个体系,可能有两方面的原因。一是该软件还没有移植到所定义的体系上;二是该软件含有特定的机器码(汇编语言),它与别的体系不兼容。
此域描述格式为:
Excludearch : 体系1 [体系2] ...
注: []所括为可选项,各体系之间以空格分隔。
如果当前体系在此域值之中,则RPM制作软件包时将报错退出,请看下面的例子。
在lze-6.0-2.spec文件头部分加入一行:
Excludearch : i386
再运行建包命令rpm -bb(<<精通RPM之七--制作篇(下)>>将讲到):
# rpm -bb lze-6.0-2.spec
Architecture is excluded: i386
#
由上看出,RPM提示了“体系不适用: i386”的错误。
3.2 Exclusivearch :
此域定义软件包适用的体系。其描述格式与Excludearch类似:
Exclusivearch : 体系1 [体系2] ...
注: []所括为可选项,各体系之间以空格分隔。
假如在lze-6.0-2.spec文件头加入一行:
Exclusivearch : i386 sparc
再运行建包命令将会怎么样:
# rpm -bb lze-6.0-2.spec
Executing: %prep
预处理脚本程序(prep)开始执行
Executing: %build
编译连接脚本程序(build)开始执行
Executing: %install
安装脚本程序(install)开始执行
Processing files: lze
Finding Provides: (using /usr/lib/rpm/find-provides)...
Finding Requires: (using /usr/lib/rpm/find-requires)...
Provides: lze-edit
PreReq: /bin/sh
Requires: /bin/sh ld-linux.so.2 libc.so.6 libc.so.6(GLIBC_2.0) libc.so.6(GLIBC_2.1)
Wrote: /usr/src/dist/RPMS/i386/lze-6.0-2.i386.rpm
#
看,此次建包(lze-6.0-2.i386.rpm)成功了,因为当前的体系(i386)正好适用。
3.3 Excludeos :
此域定义软件包不适用的操作系统。RPM可选的操作系统请参考文件/usr/lib/rpm/rpmrc中的os_canon项目。
其描述格式为:
Excludeos : 操作系统1 [操作系统2] ...
注: []为可选项,操作系统之间以空格分隔。例如:
Excludeos : irix aix solaris
注: 如将此行加入到lze的描述文件中,则它会指示RPM不在irix,aix,solaris这三个操作系统上建立lze软件包。如果当前操作系统是三者之一,则RPM会报错并中止软件包的制作。
如:
# rpm -bb lze-6.0-2.spec
OS is excluded: Solaris
#
3.4 Exclusiveos :
此域定义软件包适用的操作系统。其描述格式为:
Exclusiveos : 操作系统1 [操作系统2] ...
注: []为可选项,操作系统之间以空格分隔。例如:
Exclusiveos : linux solaris
4. 目录相关
4.1 Prefix :
此域定义可重定位的目录前缀,可在描述文件中书写多次。其描述格式为:
Prefix : 目录前缀1 [目录前缀2] ...
注: []为可选项,各目录前缀之间均以空格分隔。例如:
Prefix : /usr /etc
它也可写作:
Prefix : /usr
Prefix : /etc
RPM利用可重定位的目录前缀,实现了软件包的重定位安装, 使软件中的文件不必固定在某
个绝对位置,这种做法很好。LZE软件包描术文件lze-6.0-2.spec中就定义了一个可重定位
的前缀/usr(见第15行),这样,安装时就可将该包中在/usr目录下的文件重定位到用户指定
的目录,如:
# rpm -i --prefix /tmp lze-6.0-2.i386.rpm
#
或者:
# rpm -i --relocate /usr=/tmp lze-6.0-2.i386.rpm
#
注: 此命令安装lze包,将其中含/usr重定位目录前缀的文件定位到/tmp目录。如包中
的/usr/bin/lze文件安装后,因重定位而成了/tmp/bin/lze。(RPM安装命令使用方法请参考<<精通RPM之二--安装篇>>)
4.2 Buildroot :
此域定义的是软件包所包含的文件共有的根目录,此根目录仅供RPM建立软件包时使用。即当RPM建立软件包时,将设定此目录为根(调用chroot函数),提取所需文件,生成软件包。
例如: 当Buildroot设定为/tmp时,对于LZE包描述文件中所包含的/usr/bin/lze文件,RPM实际打包的则是/tmp/usr/bin/lze,但对生成的包查询后可以发现:原文件名并未改变,还是/usr/bin/lze。
如此说来,这就很有意思了。一般用户通过设定Buildroot,也可以象超级用户(root)那样自由地建立各种各样的软件包了,即使包中有那些唯有超级用户才可以操作的目录或文件。安装这样的包与安装由超级用户建立的包,是没有什么分别的。
此域的描述格式很简单:
Buildroot : 目录
如,上例可定义为:
Buildroot : /tmp
5. 源码相关
下列四个域均是为制作源码包而设计的。源码包里有什么?用户可以通过查询包的文件列表得到,命令是“rpm -qpl 源码包文件”(请参阅<<精通RPM之五--查询篇>>有关内容)。一般情况下,源码包里有这么四类文件: 一是程序源码(SOURCE),二是源码补丁(PATCH),三是软件包描述文件,四是图标文件(ICON)。通过安装源码包,用户可以轻松地实现现场编 译、连接和应用,同时更方便了软件开发者与软件包制作者:他们维护程序容易了,并且维护过后可以很快地生成执行代码包与源码包。这,也是所有人钟爱RPM 的重要原因之一。
5.1 Source :
此域定义RPM打包时要包含的程序源码文件。这些文件一般先用tar命令打包,然后再用gzip压缩。一个描述文件中可包含多个Source域, 当有多个这样的域时,需要进行编号:第1个编为Source0(也可直接用Source),第2个编为Source1,第3个编为Source2等等。此 域的描述格式为:
Source[编号] : 源码文件
注: []所括为可选项。具体用法如:
Source0 : lze-6.0-2.tar.gz
Source1 : lzeime-wb-6.0-2.tar.gz
Source2 : lzeime-py-6.0-2.tar.gz
Source3 : lze-lib-6.0-2.tar.gz
注: 此域域值可以采用URL(统一资源定位)的形式,如LZE描述文件第14行。采用这种形式,主要是给其它用户提供该源码的位置信息。在RPM制作源包时, 它提取的是最后的文件名lze-6.0-2.tar.gz,而不是http://zhsoft.myetang.com/lze- 6.0-2.tar.gz(URL前面的内容被RPM忽略了)。
5.2 NoSource :
在上例中,假如在打包时不想包含Source1与Source2定义的文件,那该怎么办?
办法之一是将其所在行删除掉;
办法之二是将其所在行注释掉(即所在行前面加#号);
办法之三就是定义Nosource域,此域可重复。其描述格式为:
NoSource : 源码域编号
本例可写作:
NoSource : 1
NoSource : 2
注: 其中的1与2为编号,表示Source1和Source2。
注意: 如果软件包描述文件中没有NoSource域,则RPM生成的源码包名字格式为"软件名-版本号-释出号.src.rpm"。如果使用了NoSource 域,则RPM生成的源码包名字格式为"软件名-版本号-释出号.nosrc.rpm"(单从名字就可看出源码包包含的文件不完整)。
5.3 Patch :
Patch的本义是补丁,用在这里指的是源程序的补丁,它是用diff命令比较新老源程序所产生的输出(命令为“diff -Nur 旧文件 新文件 >补丁文件”),而系统中的patch命令又可利用此输出将老版本的源程序升级为新版本。
此域定义RPM制作源码包时所要包含的补丁文件,该文件的命名建议用"软件名-版本号.补丁功能.patch"的格式。一个软件包描述文件中可有 多个Patch域,当有多个这样的域时,也需要象Source域那样进行编号(注:第1个域编为Patch0,也可省略0,用Patch)。
此域的描述格式为:
Patch[编号] : 源码补丁文件
注: []所括为可选项。具体用法如:
Patch0 : blather-4.5-bugfix.patch
Patch1 : blather-4.5-config.patch
Patch2 : blather-4.5-somethingelse.patch
注: 此域的域值也可以象Source域一样,采用URL的形式,RPM仅提取其中的文件名供其使用。
5.4 NoPatch :
此域的功能类似NoSource,其定义的编号对应的补丁文件RPM不作打包处理。此域在描述文件中可重复出现。如上例,若不想让源码包包含Patch0与Patch2域所指示的补丁文件,则可在描述文件写上这么两行:
NoPatch : 0
NoPatch : 2
注意: 如果软件包描述文件中没有NoPatch域,则RPM生成的源码包名字格式为"软件名-版本号-释出号.src.rpm"。如果使用了NoPatch域, 则RPM生成的源码包名字格式为"软件名-版本号-释出号.nosrc.rpm"(单从名字就可看出源码包包含的文件不完整)。
三、功能段
见第19-86(即文件头以下的部分)。
何谓功能段?可以这么说,功能段是描述软件包的重要数据和操作指令的段落,它包括段名与段内容两部分。没有功能段,RPM便制作不出任何包裹文 件。功能段的段名都是以百分号(%)开始的,占用一行。功能段的段内容范围是这样界定的:它从该功能段段名下一行开始到下一个功能段段名的前一行或到描述 文件结束。如LZE描述文件,%description段是从第19行到第28行(%prep段从第29行开始),第19行为段名,第20-28行为段内 容。而%prep段是从第29行到第32行(第33行%build段开始),其段名在第29行,段内容在第30-32行。另外要注意的是,各个功能段的位 置是自由的,可放在文件头以下的任何位置,不必拘泥某一固定位置。
必选的功能段
描述文件中,必选的功能段有:
1. %description
本段是描述段,段的内容是对软件包进行较为详细的介绍,不象文件头的Summary域仅用一句话说明。介绍的文本形式自由,可任意换行,不受限制。具体请参见LZE描述文件第20-27行。
本段段名描述格式是:
%description [子包选项]
其中,子包选项的格式为:[-n] 子包名
注: []所括为可选项。
三种形式的描述段段名:
(1) 段名格式为“%description”时:
本功能段描述的内容是关于父包的。父包也可叫作主软件包,它用软件名来命令,其名字格式是:软件名-版本号-释出号.体系.rpm。如:lze-6.0-2.i386.rpm。
(2) 段名格式为“%description 子包名”时:
本功能段描述的内容是关于子包的。子包选项中没有-n选项时,子包是用软件名加子包名的形式命名,格式为: 软件名-子包名-版本号-释出号.体系.rpm。如分成两个子包的LZE软件:lze-bin-6.0-2.i386.rpm(执行程序包),lze- config-6.0-2.i386.rpm(配置文件包)。
(3) 段名格式为“%description -n 子包名”时:
本功能段描述的内容也是关于子包的。当子包选项中有-n选项时,子包直接采用子包名的形式命名。它不包含软件名,命名格式为: 子包名-版本号-释出号.体系.rpm。如分成两个子包的LZE软件: bin-6.0-2.i386.rpm(执行程序包),config-6.0-2.i386.rpm(配置文件包)。注意:这种类型的子包内容通常是可被 其它软件包共用的函数库,如果专用,则尽量不要采用这样形式来定义子包。
2. %files
本段是文件段,它定义的是软件包需要包含哪些文件。本段通常放在描述文件尾部,以便于添加文件名,便于编辑。
本段段名描述格式为:
%files [子包选项] [-f 文件名]
注: []所括为可选项。
当没有任何选项时,本段内容定义的是父包要打包的文件列表;
当有子包选项时,本段内容定义的则是子包要打包的文件列表;
当选择-f选项时,RPM除了从文件段读取打包文件列表外,还将从指定的文件中读取要打包的文件列表。指定的文件中,一个文件名占用一行。此选项 方便了软件包制作者,他们可以通过程序自动产生有关软件的文件列表,并将其写入到一个特定的文件中,这样制作软件包时,只需引用一下这个文件,RPM就会 自动从这个文件中读取文件名并将其加入包中。如果没有此选项,软件包制作者只能在文件段里,将要打包的文件名一个一个写进去,有点麻烦。
文件段的内容格式为:
[修饰符1 [修饰符2] ...] 文件名
其中:修饰符是可选的,一个文件可以有多个修饰符,文件名必须以/开头(绝对路径形式)。
修饰符有以下几类:
(1) 文件相关
* %doc :
此修饰符设定文件类型为说明文档(参见LZE描述文件第72,73行);
* %config :
此修饰符设定文件类型为配置文件(参见LZE描述文件第70,71行);
* %config(missingok) :
此修饰符设定文件类型为配置文件,且此文件可丢失。即使丢失了,RPM在卸载软件包时并不认为这是个错误,并不报错。
此修饰符通常用于那些软件包安装后建立的符号连接文件,如/etc/rc.d/rc2.d/S55named等。此类文件在软件包卸载后可能需要删除,所以丢失了也不要紧。
* %config(noreplace) :
此修饰符设定文件类型为配置文件,且如果安装时系统中有同名的文件,则软件包中的这个文件将换个名字安装,其文件名后缀加个.rpmnew。(如 果不用此修饰符,则安装时RPM若发现有同名文件,则RPM会将系统中的这个文件换个名字,其后缀加上.rpmorig,而软件包中的文件则还用原来的名 字。)在软件包卸载时,系统中的同名文件被RPM换个名字保存起来,其后缀加上了.rpmsave。
如描述文件的文件段中定义了这么一行:
%config(noreplace) /etc/hello
则制成的包在安装时,若系统中已有此文件/etc/hello,则RPM会提示:
warning: /etc/hello created as /etc/hello.rpmnew
这表明包中的/etc/hello文件被创建为/etc/hello.rpmnew文件了。
如果卸载这个软件包,则系统中的/etc/hello将会改名为/etc/hello.rpmsave。
* %ghost :
此修饰符所修饰的文件,其内容不被包含到软件包中。这样的文件一般是日志文件(log file)一类的文件,其文件属性(文件名,属主,属组等)很重要,但是文件内容并不重要。用此修饰符后,RPM仅将其文件属性加入包中。
* %attr :
此修饰符设定文件的属性信息,使用格式为:
%attr(权限,属主,属组)
注: 权限常用数字形式(八进制),属主和属组可以是数字,也可以是字符串。如果文件的权限,属主和属组想使用系统默认值,则可用减号(-)表示它。
如下例采用两个修饰符,定义/etc/funkey.def文件的权限为755,属主默认,属组为root,类型为配置文件:
%attr(755,-,root) %config /etc/funkey.def
* %verify :
此修饰符设定文件需要校验的那些属性。这些属性有:owner(属主),group(属组),mode(权限),md5(MD5检查和),size(大小),maj(主设备号),min(从设备号),symlink(符号连接),mtime(最后修改时间)。
此修饰符使用格式为:
%verify([not] owner group mode md5 size maj min symlink mtime)
注: not可选。当选用not时,表明需要校验除选定属性以外的那些属性。
如下例指示RPM校验/dev/ttyS0文件时,要校验其权限,MD5检查和,大小,主设备号,从设备号,符号连接和最后修改时间共七项属性信息:
%verify(mode md5 size maj min symlink mtime) /dev/ttyS0
这也可以采用not选项来实现,因为除去属主owner和属组group两项属性,剩下的就是需要校验的属性了:
%verify(not owner group) /dev/ttyS0
(2) 目录相关
* %docdir :
此修饰符定义说明文档前缀,这样,后面所有含指定文件名作为前缀的文件,RPM打包时会将其类型统一设定为说明文档。
例如某描述文件的文件段中有这么三行:
/root/readme
%docdir /root
/root/mydoc.txt
此例指明/root为说明文档的前缀,因为/root/mydoc.txt在%docdir的下一行,所以RPM打包时会设定此文件的类型为说明文档。而/root/readme文件则不做此设定,因为它在%docdir定义之前。
通过此修饰符,用户可以很方便地设定说明文档一类的文件,因为它们通常固定在某个目录下面,有着共同的前缀。
* %dir :
RPM在制作软件包时,如果要打包的文件是个目录,那么RPM会将该目录下面的所有文件包含到软件包中。(注意:如果要打包的文件是个符号连接, 此符号连接又指向一个目录,则RPM并不会将其视作目录,只会把它当为普通文件处理。)如果仅想将这个目录名包含到软件包中,制作者用此修饰符修饰一下这 个目录名就行了。
如: /etc是个系统目录,其下有多个文件,如果想将其均加入包中,描述文件的文件段里可写上这么一行:
/etc
如果仅想包含此目录,则可用:
%dir /etc
(3) 另类修饰符
此类只有一个%defattr。说它是另类修饰符,是由于它设定的是默认的文件属性,而非特定的某个文件。它一般放在文件段内容的第一行。
其使用格式为:
%defattr(权限,属主,属组)
其中: 权限,属主和属组都可以使用减号(-)。使用减号的属性将由系统设定。
例如: %defattr(022,zzz,zhsoft) 设定其后的所有文件权限为022,属主为zzz,属组为zhsoft;又如: %defattr(-,zzz,-) 则是设定其后的所有文件属主为zzz,权限与属组由系统设置。
可选的功能段
描述文件中,可选功能段的内容都是些脚本程序。(LZE描述文件中多个脚本程序中仅含一个echo命令)
可选的功能段的描述格式为:
功能段名 [子包选项]
注: 子包选项为"[-n] 子包名"。当无子包选项时,段内容描述的是父包的脚本程序。当有子包选项时,段内容则是描述子包的脚本程序。
可选的功能段可分为如下三类:
1. 建包用功能段:
RPM通过源程序来建立一个软件包时,要执行预处理,编译,安装和清理四项操作,分别对应于%prep,%build,%install和%clean四个段。
下面按其执行顺序逐段进行说明:
1.1 %prep :
此为预处理段,其内容为预处理脚本程序。该程序完成以下任务:
* 建立软件编译用目录;
* 将源程序解压缩;
* 通过打补丁,升级源程序;
* 执行其它一些操作,使源程序随时可进行编译。
在此脚本程序中,可使用如下两个宏命令:
1.1.1 %setup
这个宏利用系统中的gzip与tar等命令,来解压源程序包。RPM会自动探测源程序包是否压缩,如果压缩,它会用gzip将其解压缩,否则直接用tar命令展开包中文件。其使用格式为:
%setup [-n name] [-c] [-D] [-T] [-b N] [-a N]
注: []所括为可选项。
(1) 当没有任何选项时:
这个宏用来解压默认的源程序包(由文件头Source或Source0域指定)。注意:源程序包中的文件应用"软件名-版本号"作为其上层目录, 这样%setup宏就可以正常工作。如果不以"软件名-版本号"作为其上层目录,则%setup宏工作时有一个指令"cd 软件名-版本号"(转目录)会因为系统中没有此目录而出错退出(除非在此宏上面加上建立此目录的命令)。如LZE软件源程序所在的目录为lze-6.0, 我需要用命令"tar cvzf lze-6.0-2.src.tgz lze-6.0"将源程序打包并压缩,这样的包就可以被%setup宏正确使用了。
下面是%setup宏命令所执行的一系列命令: (指令前面为行号)
1 cd /usr/src/dist/BUILD
2 echo "预处理脚本程序(prep)开始执行"
3 cd /usr/src/dist/BUILD
4 rm -rf lze-6.0
5 /bin/gzip -dc /usr/src/dist/SOURCES/lze-6.0-2.src.tgz | tar -xvvf -
6 STATUS=$?
7 if [ $STATUS -ne 0 ]; then
8exit $STATUS
9 fi
10 cd lze-6.0
11 [ `/usr/bin/id -u` = '0' ] && /bin/chown -Rhf root .
12 [ `/usr/bin/id -u` = '0' ] && /bin/chgrp -Rhf root .
13 /bin/chmod -Rf a+rX,g-w,o-w .
14 exit 1
看,第10行就有一个转到lze-6.0目录的命令,如果没有这个目录,程序就会出错退出了。也许你要问:这些指令你是怎么知道的?其实这很简 单,只要在%setup宏下面加上一句"exit 1"命令,让预处理脚本程序非正常退出即可。这样RPM所执行的预处理脚本程序作为临时文件在其退出时并未删除,只要看一下这个文件(在/var/tmp 目录下以rpm-tmp开头)就知道%setup宏命令做什么了。
(2) -n name :
上面已经谈到,源程序包中的文件应采用"软件名-版本号"作为上层目录。如果用了别的什么目录(如name),%setup宏无法正常工作,那该 怎么办?没关系,可以用-n选项,引用一下这个目录(name)就行了。假如我的LZE源程序包中的文件是以lze为上层目录,那么我就可以 用"%setup -n lze"宏命令来解压缩该包。
(3) -c :
此选项的作用是创建上层目录("软件名-版本号"目录)并转到这个目录。对于LZE软件,其效果相当于在上例的第4行与第5行之间加上这么两行命令:
mkdir -p lze-6.0
cd lze-6.0
它适用的情况是:有的源程序包是在源程序所在目录下打的包,所以其中的文件都没有上层目录。这样的话,要想正确解压,必须创建上层目录。
(4) -D :
本选项的作用是在解压源程序包之前不要删除软件的上层目录(软件名-版本号)。在上例中,其效果是不执行第4行的命令(rm -rf lze-6.0)。
(5) -T :
本选项的作用是不解压默认的源程序包(由文件头的Source或Source0域所定义)。在上例中,其效果是不执行第5-9行的命令:第5行是 解压源程序包(用gzip -dc将包的内容解压缩到管道中,再由tar -xvvf -从管道中读取数据并展开),第6-9行是检查解压命令的返回值,非0时执行非正常退出。
(6) -b N :
本选项指示RPM在转到上层目录前解压第N个源程序包(由文件头SourceN域定义)。这适用于含上层目录的源程序包。注意:如果使用此选项时 不同时使用-T选项,则RPM解压的是两个源程序包,一个是默认的包(由Source或Source0域定义),一个是-b选项指定的包(由 SourceN域定义)。这样,当N等于0时,默认的源程序包将被解压两次。所以,如果想仅解压指定源程序包,请同时使用-T选项,以禁止解压默认的源程 序包。
下面的宏命令仅解压第1个源程序包,然后转到上层目录:
%setup -b 1 -T
(7) -a N :本选项指示RPM在转到上层目录后再解压第N个源程序包(由文件头SourceN域定义)。这适用于不含上层目录的源程序包。使用本选项时,一般加上 -c选项,以创建上层目录并转到此目录。注意:如果使用此选项时不同时使用-T选项,则RPM解压的是两个源程序包,一个是默认的包(由Source或 Source0域定义),一个是-a选项指定的包(由SourceN域定义)。这样,当N等于0时,默认的源程序包将被解压两次。所以,如果想仅解压指定 源程序包,请同时使用-T选项,以禁止解压默认的源程序包。
下面的宏命令让RPM先转到上层目录,再仅解压第2个源程序包:
%setup -T -a 2
1.1.2 %patch
此宏利用系统中的patch命令,来给指定的源程序包打补丁,从而将程序升级。其使用格式为:
%patch [-P N] [-p N] [-b name] [-E]
注: []所括为可选项。
为了说明下列选项的作用,我们为LZE软件包描述文件中定义三个补丁文件:
Patch0 : lze-patch.zero
Patch1 : lze-patch.one
Patch2 : lze-patch.three
(1) 当没有任何选项时:
没有任何选项时,该宏使用的是默认的补丁文件(第0个补丁文件),即由文件头Patch或Patch0域所定义的文件(LZE包使用lze-patch.zero)。
该宏在执行时,扩展为以下指令:
echo "Patch #0:"
patch -p0 -s < /usr/src/dist/SOURCES/lze-patch.zero
注: 第一行指令是利用echo命令向屏幕输出字符串“Patch #0:”。第二行指令则是利用patch命令读取补丁文件lze-patch.zero升级源程序。
patch命令用了两个选项:(有关patch命令用法,详见其用户手册)
* -p : 这个选项用于确定patch所要操作的文件。它针对补丁文件头部的文件名,删除名字中指定数目个斜杠(/)前面的所有字符,从而得到要操作的文件名。如补 丁文件里有个文件名/usr/zzz/src/lze.c,则用-p0时patch操作的文件名不变,用-p1时则变为usr/zzz/src /lze.c,用-p2时则变为zzz/src/lze.c,如用-p4则操作的文件名变为lze.c。
* -s : 这个选项指示patch在打补丁过程中不输出任何信息,即使有错误发生。
(2) -P N :
使用此选项以指示RPM使用第N个补丁文件(由文件头PatchN域定义)。如想让RPM使用LZE的第2个补丁文件Patch2(lze-patch.three)时,可使用"-P 2"来指定。
(3) -p N :
此选项与其参数是由%patch宏直接传给patch命令的。请参见上面patch命令所用的-p选项的介绍。
(4) -b name :
当有多个patch命令操作同一个文件时,patch会将原文件换名保存(其后缀变作.orig),如lze.c会变作lze.orig。如果想 用别的名字作后缀,则可用-b设置一下,这样原文件会换名为"原文件名+后缀",如用-b ZZZ时,lze.c会换名保存为lze.cZZZ。
此选项在执行时,实际上是给patch命令传递了一个选项及参数,即--suffix name。
(5) -E :
此选项直接传给patch命令,其作用是:如果一个文件打完补丁后内容为空(字节数为0),则删除这个文件。
1.2 %build :
此为编译段,其内容为编译脚本程序。该程序完成源程序的编译和连接。一个最简单的例子就是程序中仅有一个make命令。这适用于大部分情况,因为 多数软件均有自己的makefile,这样通过make命令就可实现编译与连接。如果没有makefile的话,需要软件包制作者自己在编译段书写上一系 列的编译连接命令。
1.3 %install :
此为安装段,其内容是安装脚本程序。该程序将已编译连接好的执行程序或其它文件存放到指定目录下,这些程序或文件供RPM打包时使用。一个最简单 的例子就是程序中仅用一个make install命令,从而完成安装。这也需要相应的软件有makefile维护文件。没有的话,软件包制作者也得自己写指令。
1.4 %clean :
此为清理段,其内容是清理脚本程序。此程序在RPM制作好软件包后才执行,它通常是删除那些编译连接时产生的临时文件或目录,完成缮后工作。
2. 管理用功能段:
此类段用于软件包自身的管理(安装,卸载和校验),包括%pre,%post,%preun,%postun,和%verifyscript五个功能段。
2.1 %pre :
该段内容为安装前脚本程序。它在软件包安装之前执行,通常是检测操作环境,建立有关目录,清理多余文件等等,为软件包的顺利安装做准备。本段很少使用。
其段名格式为: %pre [子包选项]
2.2 %post :
该段内容为安装后脚本程序。它在软件包安装完成之后执行,常用来建立符号连接,修改系统配置文件,运行ldconfig程序等,以利软件的正常运行。
其段名格式为: %post [子包选项]
2.3 %preun :
该段内容为卸载前脚本程序。它在软件包卸载之前执行,主要为卸载做准备。具体如,要卸载的软件包中某个程序当前正在运行时,此脚本程序必须杀掉它,否则无法正确卸载。
其段名格式为: %preun [子包选项]
2.4 %postun :
该段内容为卸载后脚本程序。它在软件包卸载后执行,完成卸载的缮后工作,如将系统配置文件inetd.conf改回原来的样子,重新运行一下ldconfig命令,将已卸载的共享库从缓冲文件ld.so.cache中删除等等。
其段名格式为: %postun [子包选项]
2.5 %verifyscript :
该段内容为校验脚本程序。RPM校验软件包时,除了执行标准的校验外,如果软件包制作者设定有此校验脚本程序,还将执行之。
其段名格式为: %verifyscript [子包选项]
下面是XFree86-libs-3.3.6-6.i386.rpm软件包中的校验脚本程序,它校验的是动态链接库目录/usr/X11R6 /lib。校验时,在/etc/ld.so.cache文件中查找/usr/X11R6/lib,如果找不到,则显示"missing",找到则显 示"found"。
# verifyscript
echo -n "Looking for /usr/X11R6/lib in /etc/ld.so.conf... "
if ! grep "^/usr/X11R6/lib$" /etc/ld.so.conf > /dev/null
then
echo "missing"
echo "/usr/X11R6/lib missing from /etc/ld.so.conf" >&2
else
echo "found"
fi
3. 交互用功能段:
这类功能段有%triggerin,%triggerun,%triggerpostun,它们的内容都是RPM用于软件包之间交互控制的脚本程序。这些脚本程序都是在系统满足指定的条件下才触发执行的:
1) %triggerin : 段内为安装时触发脚本程序,当其所在软件包与指定软件包仅有一方已安装时,安装另一方将触发此程序执行;
2) %triggerun : 段内为卸载时触发脚本程序,当其所在软件包与指定软件包都已安装时,卸载二者中的任一个将触发此程序执行;
3) %triggerpostun : 段内为卸载后触发脚本程序,只有指定软件包卸载后才触发此程序执行。
3.1 段名格式
它们的段名描述格式均为:
交互段名 [子包选项] [-p 解释程序] -- 触发条件1 [,触发条件2] ...
注: []所括为可选项。子包选项见前面介绍,不赘述。
3.1.1 -p选项:
此选项用于指定一个解释程序,来解释执行交互功能段的脚本程序。默认情况下,RPM使
用/bin/sh来执行脚本(此类脚本用SHELL语言编写,也叫SHELL程序)。有的RPM包则是使用/usr/bin/perl
来执行脚本(此类脚本是用PERL这种解释性语言写的),这就需要用-p选项来指定解释程序为
/usr/bin/perl,如:
%triggerin -- sendmail
ln -sf /usr/bin/sendmail /etc/mymailer/mailer
%triggerin -- vmail
ln -sf /usr/bin/vmail /etc/mymailer/mailer
注: 此例中定义package子软件包安装时触发脚本程序:当触发条件(fileutils>3.0,perl<1.2)满足时,用/usr/bin/perl执行脚本,即用print命令输出字符串"I'm in my trigger!"。
3.1.2 触发条件:
交互功能段的触发条件格式是:
功能名 [比较符 版本号]
其中:比较符与版本号可选。仅有一个功能名时,表明该功能存在时触发程序执行。比较符可用大于(>),等于(=),小于(<),大于等于(>=)和小于等于(<=)。
如触发条件bash,又如触发条件fileutils>3.0,这种使用均合法。
交互功能段最少有一个触发条件。当有多个触发条件时,这些条件间均以逗号(,)分隔,它们之间是"或"的关系,即只要其中有一个条件系统满 足,RPM就将执行触发脚本程序。如上面介绍-p选项时举的例子:例子中有两个触发条件fileutils>3.0和perl<1.2,在安 装软件包时,只要有一个条件满足,RPM就会执行触发脚本,即输出"I'm in my trigger!"。
3.2 交互用功能段的使用
为什么要使用交互用功能段?下面的例子很能说明问题。
假定mymailer软件包需要/etc/mymailer/mailer这个符号连接文件指向当前使用的邮件发送代理程序。如果 sendmail包安装了,那么这个符号连接文件应指向/usr/bin/sendmail程序。如果vmail包安装了,那么它应当指向/usr /bin/vmail程序。如果这两个软件包都安装了(实际上,sendmail与vmail彼此是冲突的),那么我们也无需考虑符号连接指向哪个文件 了。当然,如果这两个包都未安装,那么/etc/mymailer/mailer符号连接文件也没有理由存在了。
上述要求,我们通过为mymailer软件包编写触发脚本程序来实现,这些脚本程序在下列事件发生时,将改变/etc/mymailer/mailer符号连接的内容:
1) sendmail已安装;
2) vmail已安装;
3) sendmail卸载时;
4) vmail卸载时。
前两个事件触发的脚本程序可以这样写:
%triggerin -- sendmail
ln -sf /usr/bin/sendmail /etc/mymailer/mailer
%triggerin -- vmail
ln -sf /usr/bin/vmail /etc/mymailer/mailer
这是两个安装时被sendmail或vmail所触发脚本程序。它们将在下列情况下执行:
1) 在mymailer包已安装的情况下,安装或升级sendmail包;
2) 在mymailer包已安装的情况下,安装或升级vmail包;
3) 在sendmail包已安装的情况下,安装或升级mymailer包;
4) 在vmail包已安装的情况下,安装或升级mymailer包。
后两个事件触发的脚本程序可以这么写:
%triggerun -- sendmail
[ $2 = 0 ] || exit 0
if [ -f /usr/bin/vmail ]
then
ln -sf /usr/bin/vmail /etc/mymailer/mailer
else
rm -f /etc/mymailer/mailer
fi
%triggerun -- vmail
[ $2 = 0 ] || exit 0
if [ -f /usr/bin/sendmail ]
then
ln -sf /usr/bin/sendmail /etc/mymailer/mailer
else
rm -f /etc/mymailer/mailer
fi
这两个脚本程序在下列情况下触发执行:
1) 在sendmail包已安装的情况下,卸载mymailer包;
2) 在vmail包已安装的情况下,卸载mymailer包;
3) 在mymailer包已安装的情况下,卸载sendmail包;
4) 在mymailer包已安装的情况下,卸载vmail包。
为了确保在mymailer包卸载后符号连接文件/etc/mymailer/mailer也被删除,可以在
mymailer软件包描述文件的%postun功能段内,加上删除该文件的命令:
%postun
[ $1 = 0 ] && rm -f /etc/mymailer/mailer
注: %postun段内为卸载后执行脚本程序,在mymailer包卸载后执行。
由上看出,当一个软件包与另一个软件包存在密切关系时,我们可以通过交互用功能段实现某些文件的管理,这不仅扩展了RPM软件包管理的功能,又有助于软件包的正常运行。
4. 其它功能段
其它功能段只有一个,即%changelog。这个段的内容是软件维护记录,它记录每次软件维护的时间,维护人及其EMAIL,维护的项目等。
%changelog段内容格式为:
* 星期 月份 日子 年份 维护内容
注: 每个维护记录均以*开头,星期,月份均须为英文缩写。维护内容多时可分行编写,
每行开头最好以减号(-)开头。可以采用类似LZE方式的维护记录写作格式:(见LZE描述文件第80-85行)
一个RPM的软件包描述文件,可以仅生成一个父包或一个子包,也可以生成一个父包和多个子包。通过设定子包选项,可以使生成的子包采用"软件名- 子包名"的标准命名,也可使生成的子包采用自己的名字。一个子包,通常是按照其包含的文件的用途或类型来归并文件进而打成包裹的。象前面的LZE描述文件 很简单,它将所有文件都包含进了父包中。我们也可以将文件分类作成子软件包,如可分成执行程序子包(lze-bin),配置文件子包(lze- config)和说明文档包(lze-doc)。我们还可以只分出一个配置文件子包(lze-config),其余文件均打入父包中(lze)。通过这样 详细地分类,有助于用户管理软件包,避免安装多余的东西,同时也有助于升级。
要想创建子软件包,必须描述以下内容:
1. %package :
用此段创建一个子包。其名字由子包选项控制。子包选项为"[-n] 子包名",不选-n时,生成的子包文件为"软件名-子包名-版本号-释出号.体系.rpm";选-n时,生成的子包文件为"子包名-版本号-释出号.体系.rpm"。其应用格式为:
%package 子包选项
2. Summary
此域必须在%package下面,它定义子包功能简介(一句话说明)。格式为:
Summary : 子包简介
3. Group
此域必须在%package下面,其定义子包所属软件类别(软件类别请参见<<精通RPM之五--查询篇>>)。格式为:
Group : 软件类别
4. %description :
此描述段的内容是较为详细的子包功能介绍,介绍为文本形式,格式不作要求,可任意换行或分段。格式为:
%description 子包选项
...介绍子包功能的内容...
5. %files :
此文件段的内容是子包所要包含的文件列表。文件列表中,一个文件占用一行,还可使用多种文件修饰符。(详见<<精通RPM之七--制作篇(上)>>)
段名应用格式为:
%files 子包选项 [-f 文件名]
注意: 上述%description与%files段所用的子包选项形式,必须与%package所用的子包选项形式一致,否则的话,它们定义的不是同一个子 包,RPM检查时将报错退出。如定义过%package name后,描述段名须用%description name,文件段名须用%files name方可。而用%description -n name则不行,%files -n name也不行。
子软件包也可使用%pre,%post,%preun,%postun,%triggerin,%triggerun 和%triggerpostun等七个可选的功能段,因为它们都可使用子包选项。当使用子包选项时,它们的段内容就是用来管理子软件包的脚本程序。要注意 的是,这些段使用的子包选项形式也必须与%package段使用的子包选项形式一致。
条件语句的使用
在软件包描述文件中,可以灵活地使用条件语句,位置不限制。这些语句,用于当前体系与操作系统的判断,当条件为真或为假时,RPM均会引用其相应的描述内容。
条件语句有两种格式:
1. {%ifarch,%ifnarch,%ifos,%ifnos} 值1 [值2] ...
描述内容
%endif
注: {}所括内容必选其中之一,[]所括为可选项,各个值之间以空格分隔,%endif表示条件语句结束。
此语句的含义是:
1) 使用%ifarch时,表示如果当前体系为值1或值2...,则引用描述内容。
2) 使用%ifnarch时,表示如果当前体系不为值1或值2...,则引用描述内容。
3) 使用%ifos时,表示如果当前操作系统为值1或值2...,则引用描述内容。
4) 使用%ifnos时,表示如果当前操作系统不为值1或值2...,则引用描述内容。
如果想在LZE包描述文件的文件段增加只适用于sparc体系的文件/etc/sparc.lze和 /etc/sparc.ime,则可在文件段内加入如下语句:
%ifarch sparc
/etc/sparc.lze
/etc/sparc.ime
%endif
这样做以后,如果当前体系为sparc,则RPM在打包时会加入这两个文件。
2. {%ifarch,%ifnarch,%ifos,%ifnos} 值1 [值2] ...
描述内容1
%else
描述内容2
%endif
注: {}所括内容必选其中之一,[]所括为可选项,各个值之间以空格分隔,%else表示另外一种情况,%endif表示条件语句结束。
此语句的含义是:
1) 使用%ifarch时,表示如果当前体系为值1或值2...,则引用描述内容1,否则引用描述 内容2。
2) 使用%ifnarch时,表示如果当前体系不为值1或值2...,则引用描述内容1,否则引用描述内容2。
3) 使用%ifos时,表示如果当前操作系统为值1或值2...,则引用描述内容1,否则引用描述内容2。
4) 使用%ifnos时,表示如果当前操作系统不为值1或值2...,则引用描述内容1,否则引用描述内容2。
如果想根据当前操作系统来确定LZE包的名字,则可在描述文件头使用如下语句定义Name域:
%ifos linux
Name : lzeforlinux
%else
%ifos aix
Name : lzeforaix
%else
Name : lzeforothersys
%endif
%endif
本例中使用了嵌套的条件语句,它说明的情况是:如果操作系统为linux,则软件名定为lzeforlinux,如果操作系统为aix,则软件名定为lzeforaix,如果不是上述两个操作系统,则将软件名定为lzeforothersys。
如何在描述文件中使用宏(macros)
1. 宏是什么?
学过C语言的人都知道,宏是用来实现文本替换的,即定义了宏名与宏体后,文件中所有有宏名的地方在预处理时将被宏体替换掉。使用宏可以减少文字的录入量,方便了编程人员。在软件包描述文件中使用宏,也是基于这个目的,只不过这个宏与C语言的宏定义格式不同而已。
2. 宏的定义
描述文件中宏的定义格式为:
%define [(opts)]
注: []所括为可选项。为宏名,宏名可用字母,数字和下划线(_),并且其长度最小为3。opts为一个或多个选项,各选项之间无分隔,选项采用getopt 函数要求的形式,即选项为单个字符,如果某个选项需要参数,则需要在这个选项后加个冒号(:)。为宏体,它周围的空字符将被删掉。宏体的内容须在一行上。
如没有选项的宏定义:
%define aaa "This is my software"
如仅有一个选项的宏定义:
%define xxx(p:Z) echo %{-p:%{-p*}} %{-Z}
3. 宏的使用
宏的使用格式为:
% [opt1] [opt2]... [arg1] [arg2]...
或
%{} [opt1] [opt2]... [arg1] [arg2]...
注: []所括为可选项;为所应用的宏名,宏名可以用{}括住;opt1,opt2...为选项,均须以减号(-)开头,并且如果选项需要参数,则必须提供一个选项参数;arg1,arg2...则为宏的参数。
如上面定义的xxx宏,可这样使用:
%xxx -p zhsoft hello world<
br>
例子中,xxx宏使用一个选项-p,zhsoft为-p选项的参数,还有两个宏的参数hello和world。
注意: 宏使用时最好多换一行(即宏下面空一行),因为宏在扩展后并不换行,这样如果不多换行,则下面一行若有内容的话,宏扩展后的内容将和下面一行的内容合并在 一起,极容易出现错误。这也是笔者发现RPM宏的问题之一。还有一个问题,如果注释行上存在宏,则这个宏也将扩展,错矣!因为注释本来就是要忽略掉的,有 宏也不必再扩展了。这两个问题都需要引起RPM开发者的注意,并切实加以解决。
4. 宏体专用的宏
宏体中可使用如下专用的宏:(类似SHELL形式的宏)
1) %0 : 表示所在宏的宏名;
2) %* : 表示宏的所有参数;
3) %# : 表示宏的参数个数;
4) %{-f} : 表示如果宏使用了-f选项,则它表示-f及其选项参数;
5) %{-f*} : 表示如果宏使用了-f选项,则它表示-f所带的参数;
6) %{-f:X} : 表示如果宏使用了-f选项,则它表示X;
7) %{!-f:Y} : 表示如果宏没有使用-f选项,则它表示Y;
8) %1,%2,... : 表示宏的参数1,参数2...
如,上例中xxx宏执行时,若宏体中有上述专用的宏,则专用宏将会扩展为:
1) %0扩展为xxx;
2) %*扩展为hello world;
3) %#扩展为2;
4) %{-p}扩展为-p zhsoft;
5) %{-p*}扩展为zhsoft;
6) %{-p:good}扩展为good;
7) %{!-Z:bad}扩展为bad; (因为xxx宏未使用-Z选项)
8) %1为hello,%2为world,没有其它参数。
5. 系统内置的宏
系统内置的宏可分如下三类:
5.1 定义类
1) %define ... : 定义一个宏;(原来,%define也是一个宏啊)
2) %undefine ... : 取消一个宏;(宏取消后,此语句下面的描述文件就不能再使用这个宏了,即使使用,该宏也不会被扩展了)
5.2 调试类
1) %trace : 打印宏扩展前后的调试信息;
2) %dump : 打印活动的宏(宏名及宏体);
3) %{echo:...} : 打印...到标准错误设备;
4) %{warn:...} : 打印...到标准错误设备;
5) %{error:...} : 打印...到标准错误设备,并且返回BADSPEC值;
5.3 特殊类
这类宏的默认值通常放在/usr/lib/rpm/macros文件中,用户通过编辑自己主目录(HOME)下的.rpmmacros文件(~/.rpmmacros),可重定义这类宏,改变其默认值,以供RPM在软件包制作,安装及查询时使用自己的定义。
这类宏的定义格式为:
%
注: 为宏名,为宏体。
1) %packager,%vendor,%distribution :
这三个宏用于定义描述文件中Packager,Vendor,Distribution三个可选域的默认的域值,即如果这三个域中有哪个未在描述文件中定义,且其相对应的宏有定义,则RPM会采用其对应的宏的宏体。
如我的~/.rpmmacros文件中有这样三行:
%vendor 纵横软件制作中心
%packager 雨亦奇
%distribution 小赵'2001
这样,软件包描述文件中再也不用定义那三个域了,由此制作出来的软件包在查询时,其打包者(Packager),销售商(Vendor)及发行版(Distribution)均自动搞定了,一劳永逸。
2) %buildroot,%_provides :
这两个宏定义软件包建包时用的根目录及软件包所提供的功能。它们在打包时不会象 上面那三个宏一样主动被RPM采用,而是必须在描述文件中写那么几行。即:
%vendor 纵横软件制作中心
%packager 雨亦奇
%distribution 小赵'2001
Buildroot : %buildroot
Provides : %_provides
3) %_topdir,%_builddir,%_rpmdir,%_sourcedir,%_specdir,%_srcrpmdir :
这六个宏都是RPM制作软件包时要用的,它们在/usr/lib/rpm/macros文件中的默认值为:
%_topdir %{_usrsrc}/dist
%_builddir %{_topdir}/BUILD
%_rpmdir %{_topdir}/RPMS
%_sourcedir %{_topdir}/SOURCES
%_specdir %{_topdir}/SPECS
%_srcrpmdir %{_topdir}/SRPMS
%_topdir宏定义的是RPM制作软件包时所用目录的顶层目录,一般为/usr/src/dist(%{_usrsrc} 宏的值为/usr/src)。在顶层目录下面,又有五个子目录:
* 编译连接源程序时用的目录,由%_builddir宏定义,常用BUILD;
* 生成的RPM执行程序包存放的目录,由%_rpmdir宏定义,常用RPMS;
* 软件源程序存放的目录,由%_sourcedir宏定义,常用SOURCES;
* 软件包描述文件存放的目录,由%_specdir宏定义,常用SPECS;
* 生成的RPM源程序包存放的目录,由%_srcrpmdir宏定义,常用SRPMS。
由于宏的递归特性,我们可以通过只定义%_topdir宏来达到改变%_builddir等五个宏的目的。(注意:%_builddir等五个宏 的宏体如无特殊要求,尽量不要改变,它们是标准的定义,应该采用)这对于普通用户来说,意义非常重大。因为RPM默认的顶层目录/usr/src /dist并不是每个用户都可以随便使用的,普通用户更想在自己所有的目录下用RPM来制作些软件包。我也有这种想法,所以在~/.rpmmacros文 件里加上这么一行:
%_topdir /usr/zzz/rpm
同时,在此宏定义的目录下面建立了RPM所需的子目录,使用命令为:
$ cd /usr/zzz
$ mkdir -p rpm/{BUILD,RPMS/i386,SOURCES,SPECS,SRPMS}
$
命令中的i386是RPM默认的体系名,RPM生成的执行程序包是存放在“RPMS/体系名”目录下面的。这么做以后,我就可以在自己的目录下制作RPM软件包了,象超级用户一样自由。
4)%_excludedocs,%_ftpport,%_ftpproxy,%_httpport,%_httpproxy,%_netsharepath :
这六个宏对RPM软件包的安装和查询起作用。
* %_excludedocs : 如果其值定义为1,则RPM安装软件包时,对说明文档的默认作法是不安装;
* %_ftpport : 此宏用于定义RPM默认的FTP端口;
* %_ftpproxy : 此宏用于定义RPM默认的FTP代理服务器;
* %_httpport : 此宏用于定义RPM默认的HTTP端口;
* %_httpproxy : 此宏用于定义RPM默认的HTTP代理服务器;
* %_netsharepath : 此宏用于定义RPM默认的网络共享目录,适用于网络文件系统(NFS)。
6. 一种特殊的宏
这种宏的用法是:
%(SHELL命令及其参数)
它的结果是取指定的SHELL命令的标准输出的结果作为描述文件内容的一部分。如软件包描述文件的某个部分需要加上当前日期,则可以用:
%(date +%Y-%m-%d)
执行后,该宏将扩展为类似2001-10-31的日期数据。用户不妨在自己的描述文件的预处理段(%prep)内加上这么两行试试:
%(date +%Y-%m-%d)
exit 1
注: exit 1用于中止RPM的执行。
描述文件模板
以下所有描述文件模板均以LZE软件包制作为例,以源程序现场编译后产生的文件为准生成软件包。描述文件中一般只描述必要的部分。另外,如果文件 段的所有文件已存在于系统中,并且想直接利用打包,则可以去掉Source域,去掉RPM建包用功能段 (%prep,%build,%install,%clean)。
1. 只有父包,没有任何子包:
此描述文件见<<精通RPM之七--制作篇(上)>>。此文件中还可以去掉几个可选的功能段, 如%pre,%post,%preun,%postun,%triggerin,%triggerun,%triggerpostun。这几个段在此文件 中无实质用途,执行时仅显示RPM开始执行某个脚本程序的信息。此描述文件仅生成软件包lze-6.0-2.i386.rpm(父包)。
2. 有父包,也有子包:
描述文件如下:
1 # 文件名称: lze-6.0-2.spec1
2 # 文件功能: lze软件包描述信息
3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利
4 # 修改时间: 2001.10.31
5
6 Name: lze
7 Version: 6.0
8 Release: 2
9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用)
10 Group: Applications/Editors
11 License: Share
12 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz
13
14 %description
15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗
16 口中英文多功能编辑器。
17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十
18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特
19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎
20 添翼。10.即时翻译,按到即译。
21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。
22 它将在工作中助您一臂之力,轻松上阵,游刃有余!
23
24 %prep
25 echo "预处理脚本程序(prep)开始执行"
26 %setup
27
28 %build
29 echo "编译连接脚本程序(build)开始执行"
30 make
31
32 %install
33 echo "安装脚本程序(install)开始执行"
34 make install
35
36 # 配置文件子包
37 %package config
38 summary : 小赵编辑器LZE的配置文件
39 group : Applications/Editors
40
41 %description config
42 小赵编辑器用配置文件包括功能键定义文件与
43 输入法控制文件,用户可根据实际情况加以修改。
44
45 %files config
46 %config /etc/funkey.def
47 %config /etc/inputme.def
48
49 # 说明文档子包
50 %package doc
51 summary : 小赵编辑器LZE的说明文档
52 group : Applications/Editors
53
54 %description doc
55 小赵编辑器说明文档,详细介绍了该编辑器的
56 命令行用法及内置的各项菜单的功能与操作,对用
57 户熟悉小赵编辑器有很大作用。
58
59 %files doc
60 %doc /usr/doc/lze-6.0/README
61 %doc /usr/doc/lze-6.0/LICENSE
62
63 # 父包文件段
64 %files
65 %defattr (-,root,root)
66 /usr/bin/lze
67 /usr/bin/lzeime.py
68 /usr/bin/lzeime.wb
69 /etc/wbzc.dat
70
此描述文件生成软件包有:lze-6.0-2.i386.rpm(父包),lze-config-6.0-2.i386.rpm(配置文件子包)和lze-doc-6.0-2.i386.rpm(说明文档子包)。
3. 没有父包,只有子包:
没有父包,意味着描述文件中可以没有父包的文件段(%files),请看下面的描述文件:
1 # 文件名称: lze-6.0-2.spec2
2 # 文件功能: lze软件包描述信息
3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利
4 # 修改时间: 2001.10.31
5
6 Name: lze
7 Version: 6.0
8 Release: 2
9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用)
10 Group: Applications/Editors
11 License: Share
12 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz
13
14 %description
15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗
16 口中英文多功能编辑器。
17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十
18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特
19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎
20 添翼。10.即时翻译,按到即译。
21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。
22 它将在工作中助您一臂之力,轻松上阵,游刃有余!
23
24 %prep
25 echo "预处理脚本程序(prep)开始执行"
26 %setup
27
28 %build
29 echo "编译连接脚本程序(build)开始执行"
30 make
31
32 %install
33 echo "安装脚本程序(install)开始执行"
34 make install
35
36 # 配置文件子包
37 %package config
38 summary : 小赵编辑器LZE的配置文件
39 group : Applications/Editors
40
41 %description config
42 小赵编辑器用配置文件包括功能键定义文件与
43 输入法控制文件,用户可根据实际情况加以修改。
44
45 %files config
46 %config /etc/funkey.def
47 %config /etc/inputme.def
48
49 # 说明文档子包
50 %package doc
51 summary : 小赵编辑器LZE的说明文档
52 group : Applications/Editors
53
54 %description doc
55 小赵编辑器说明文档,详细介绍了该编辑器的
56 命令行用法及内置的各项菜单的功能与操作,对用
57 户熟悉小赵编辑器有很大作用。
58
59 %files doc
60 %doc /usr/doc/lze-6.0/README
61 %doc /usr/doc/lze-6.0/LICENSE
62
63 # 执行程序子包
64 %package bin
65 summary : 小赵编辑器LZE的执行程序
66 group : Applications/Editors
67
68 %description bin
69 小赵编辑器执行程序为lze,五笔输入法服务器执行程序
70 为lzeime.wb,拼音输入法服务器执行程序为lzeime.py。
71
72 %files bin
73 %defattr (-,root,root)
74 /usr/bin/lze
75 /usr/bin/lzeime.py
76 /usr/bin/lzeime.wb
77 /etc/wbzc.dat
78
此描述文件生成三个软件包:lze-config-6.0-2.i386.rpm(配置文件子包),lze-doc-6.0-2.i386.rpm(说明文档子包),lze-bin-6.0-2.i386.rpm(执行程序子包)。
制作篇(下)
(雨亦奇 赵建利 2001年12月10日 09:38)
要想制作RPM格式的软件包,需使用如下命令格式:
rpm-bX[制作选项1制作选项2...]描述文件1描述文件2...
注:-bX可用-tX替换,效果有所不同:使用-b时,需要在命令行上指定软件包描述文件;而使用-t时,在命令行上需要指定的不是软件包描述文 件,而是含有此描述文件的TAR格式的包裹文件(必须用gzip压缩),RPM在准备制作软件包时,会自动从此包裹文件中提取描述文件,根据其中的建包指 令,生成RPM格式的软件包。注意:此描述文件必须以.spec为后缀,其中必须有Source域,并且此域定义的源程序包必须存放在当前目录下,否则的 话,RPM将报错退出。
注意,-bX与-tX当中的X,取不同的值时,RPM将执行不同的操作:(下面各个例子均对LZE的描述文件lze-6.0-2.spec进行操作,有的则通过管道技术,用nl命令给输出加上行号,以便解释)
1)X=p时,指示RPM执行描述文件中的预处理段(%prep)的脚本程序。该脚本程序一般用来解压源程序包,并且为源程序打补丁,升级源程序。
#rpm-bplze-6.0-2.spec2>&1|nl
1Executing:%prep
2+umask022
3+cd/usr/src/dist/BUILD
4+echo'预处理脚本程序(prep)开始执行'
5预处理脚本程序(prep)开始执行
6+cd/usr/src/dist/BUILD
7+rm-rflze-6.0
8+/bin/gzip-dc/usr/src/dist/SOURCES/lze-6.0-2.src.tgz
9+tar-xvvf-
10drwxr-xr-xroot/root02001-11-0216:02lze-6.0/
11-rw-------root/root2462262001-11-0216:00lze-6.0/lze.c
12-rw-------root/root982492001-11-0216:00lze-6.0/lzeime.wb.c
13-rw-------root/root3399022001-11-0216:00lze-6.0/lzeime.py.c
14-rw-r--r--root/root12832001-11-0216:00lze-6.0/funkey.def
15-rwxr--r--root/root2502001-11-0216:00lze-6.0/inputme.def
16-rw-r--r--root/root8132742001-11-0216:00lze-6.0/wbzc.dat
17-rw-------root/root4742001-11-0216:02lze-6.0/makefile
18+STATUS=0
19+'['0-ne0']'
20+cdlze-6.0
21++/usr/bin/id-u
22+'['0=0']'
23+/bin/chown-Rhfroot.
24++/usr/bin/id-u
25+'['0=0']'
26+/bin/chgrp-Rhfroot.
27+/bin/chmod-Rfa+rX,g-w,o-w.
28+exit0
#
注:本例中第1行显示的"Executing:%prep"表明RPM开始执行预处理段的脚本程序。例中行号后那些以加号(+)开始的行均为预处理段脚本程序的指令,其它内容则为指令执行所输出的结果。从预处理段脚本程序所执行的指令,我们就可以看出RPM正在做什么:
第2行:设置文件创建掩码;
第3行:转到RPM默认的编译目录;
第4行:回显字符串,这才是用户所写的预处理段脚本程序的开始,第2,3行均是RPM增加的指令;
第6-27行:为%setup所扩展出来的指令及其执行结果,其中可以看到RPM用gzip命令解压LZE的源程序包(第8行),而后用tar命令展开源程序包(第9行)。
第28行:正常退出,返回值为0。
2)X=l时,指示RPM检查文件段(%files),看其中的文件是否存在。如果不存在,则RPM会报错退出。
#rpm-bl-vvlze-6.0-2.spec|nl
1Processingfiles:lze
2D:File0:0100644root.root/etc/funkey.def
3D:File1:0100644root.root/etc/inputme.def
4D:File2:0100644root.root/usr/doc/lze-6.0-2/README
5Filenotfound:/usr/doc/lze-6.0-2/LICENSE
6D:File3:0100555root.root/usr/bin/lze
7D:File4:0100511root.root/usr/bin/lzeime.py
8D:File5:0100511root.root/usr/bin/lzeime.wb
9D:File6:0100644root.root/etc/wbzc.dat
10Provides:lze-edit
11PreReq:/bin/sh
12Requires:/bin/sh
#
注:本例命令中使用了通用选项-vv,以输出RPM检查时的调试信息(以行号和D:开始的行)。
由上看出,RPM对文件段的所有文件逐一进行检查,找到的文件显示其权限,属主和属组信息,结果发现/usr/doc/lze- 6.0-2.LICENSE文件不存在,于是报出错误(File not found)(见第5行)。RPM在检查过文件后,还显示出描述文件要求LZE提供的功能(Provides)和所需的功能(Requires)。
3)当X=c时,指示RPM依次执行预处理段(%prep),编译段(%build)的脚本程序。编译段的脚本程序用来编译连接软件的源程序,生 成可执行程序,通常一个make命令足够。因为一个有良好习惯的程序员会把Makefile(程序维护文件)写好,以便其它程序员编译该软件。如果某个软 件没有维护文件的话,用户要么自己写个Makefile,要么在编译段里写上软件编译与连接的各项命令。
4)当X=i时,指示RPM依次执行预处理段(%prep),编译段(%build)和安装段(%install)的脚本程序。安装段的脚本程序 的任务是将编译连接好的执行程序拷贝到适当的目录(如/bin,/usr/bin等公共执行目录),以便打包或执行。它通常执行的指令是make install。
5)当X=b时,指示RPM依次执行预处理段(%prep),编译段(%build),安装段(%install)的脚本程序,之后根据文件段(%files)的文件列表,将文件打包,生成RPM执行程序包,最后执行清理段(%clean)。
#rpm-bblze-6.0-2.spec2>&1|nl
1Executing:%prep
2+umask022
3+cd/usr/src/dist/BUILD
4+echo'预处理脚本程序(prep)开始执行'
5预处理脚本程序(prep)开始执行
6+cd/usr/src/dist/BUILD
7+rm-rflze-6.0
8+tar-xvvf-
9+/bin/gzip-dc/usr/src/dist/SOURCES/lze-6.0-2.src.tgz
10drwxr-xr-xroot/root02001-11-0217:04lze-6.0/
11-rw-------root/root2462262001-11-0216:00lze-6.0/lze.c
12-rw-------root/root982492001-11-0216:00lze-6.0/lzeime.wb.c
13-rw-------root/root3399022001-11-0216:00lze-6.0/lzeime.py.c
14-rw-r--r--root/root12832001-11-0216:00lze-6.0/funkey.def
15-rwxr--r--root/root2502001-11-0216:00lze-6.0/inputme.def
16-rw-r--r--root/root8132742001-11-0216:00lze-6.0/wbzc.dat
17-rw-------root/root4742001-11-0216:02lze-6.0/makefile
18-rw-r--r--root/root12552001-11-0217:04lze-6.0/getinputme.c
19+STATUS=0
20+'['0-ne0']'
21+cdlze-6.0
22++/usr/bin/id-u
23+'['0=0']'
24+/bin/chown-Rhfroot.
25++/usr/bin/id-u
26+'['0=0']'
27+/bin/chgrp-Rhfroot.
28+/bin/chmod-Rfa+rX,g-w,o-w.
29+exit0
30Executing:%build
31+umask022
32+cd/usr/src/dist/BUILD
33+cdlze-6.0
34+echo'编译连接脚本程序(build)开始执行'
35编译连接脚本程序(build)开始执行
36+make
37cc-fwritable-strings-DUSE_AS_LZE-DFOR_LINUX-s-I/usr/zzz/src/include-DFOR_LZE_INPUTME-olze/usr/zzz/src/li-
38bsrc/mycurses.clze.cgetinputme.c/usr/zzz/src/my.a
39cc-DFOR_LINUX-s-I/usr/zzz/src/include-olzeime.wbgetinputme.clzeime.wb.c/usr/zzz/src/my.a
40lzeime.wb.c:Infunction`do_service':
41lzeime.wb.c:1409:warning:passingarg5of`bsearch'fromincompatiblepointertype
42cc-DFOR_LINUX-s-I/usr/zzz/src/include-olzeime.pygetinputme.clzeime.py.c/usr/zzz/src/my.a
43+exit0
44Executing:%install
45+umask022
46+cd/usr/src/dist/BUILD
47+cdlze-6.0
48+echo'安装脚本程序(install)开始执行'
49安装脚本程序(install)开始执行
50+makeinstall
51installing...
52done
53+exit0
54Processingfiles:lze
55FindingProvides:(using/usr/lib/rpm/find-provides)...
56FindingRequires:(using/usr/lib/rpm/find-requires)...
57Provides:lze-edit
58PreReq:/bin/sh
59Requires:/bin/shld-linux.so.2libc.so.6libc.so.6(GLIBC_2.0)libc.so.6(GLIBC_2.1)
60Wrote:/usr/src/dist/RPMS/i386/lze-6.0-2.i386.rpm
61Executing:%clean
62+umask022
63+cd/usr/src/dist/BUILD
64+cdlze-6.0
65+echo'建包结束后清理脚本程序(clean)开始执行'
66建包结束后清理脚本程序(clean)开始执行
67+exit0
#
注:本例中,各行解释如下:
第1行:显示RPM开始执行预处理段(%prep);
第2-29行:为预处理段(%prep)脚本程序执行的命令与结果,命令前有加号(+),结果前面则没有。预处理完成了LZE源程序包的解压缩(gzip-dc)与包的展开(tar-xvvf),从而为源程序的编译打下了基础;
第30行:RPM表示开始执行编译段(%build);
第31-43行:为编译段(%build)脚本程序执行的命令与结果。脚本程序执行的make维护命令,该命令执行了cc编译程序,以编译与连接LZE软件;
第44行:RPM表示开始执行安装段(%install);
第45-53行:为安装段(%install)脚本程序执行的命令与结果。本段程序执行了makeinstall命令,将LZE的执行程序等文件拷贝到系统目录下;
第54行:RPM显示:开始处理LZE的文件(为%files文件段的内容);
第55-59行:RPM利用/usr/lib/rpm/find-provides程序查找LZE提供的功能,又利用/usr/lib/rpm/find-requires查找LZE所依赖的功能,以设定LZE的依赖关系;
第60行:制作完成LZE执行程序包,文件名为lze-6.0-2.i386.rpm,在/usr/src/dist/RPMS/i386目录下;
第61行:RPM显示:开始执行清理段(%clean)脚本程序,本段程序用于清理临时文件;
第62-67行:为清理段(%clean)脚本程序执行的命令与结果。
从上我们可以清楚看出RPM制作软件包的工作流程:预处理段,编译段,安装段,软件包制作,清理段。
6)当X=s时,指示RPM建立源码包。RPM源码包的内容包括软件包描述文件(SPEC),软件源程序,软件补丁程序,图标文件等几项。建立源码包不需要执行软件包描述文件中的各个功能段,仅需将所需文件包含到包中即可。
#rpm-bslze-6.0-2.spec
Wrote:/usr/src/dist/SRPMS/lze-6.0-2.src.rpm
#rpm-qplv/usr/src/dist/SRPMS/lze-6.0-2.src.rpm
-rw-------rootroot206711月215:44lze-6.0-2.spec
-rw-r--r--rootroot53870611月217:05lze-6.0-2.src.tgz
#
注:本例中,使用rpm-bs命令生成了LZE源码包lze-6.0-2.src.rpm(在RPM标准源码目录/usr/src/dist /SRPMS下),然后用rpm -qplv命令查询源码包中所含的文件信息,从中可以看到LZE源码包中有两个文件:一个是软件包描述文件lze-6.0-2.spec,一个是LZE源 代码包lze-6.0-2.src.tgz(TAR打包再用gzip压缩),此文件由描述文件中的Source域确定。
7)当X=a时,指示RPM依次执行预处理段(%prep),编译段(%build),安装段(%install)脚本程序,之后先生成RPM源 码包,再根据文件段(%files)的文件列表,将文件打包,生成RPM执行程序包,最后执行清理段(%clean)脚本程序,清除中间文件。此命令执行 的结果相当于先执行rpm-bs命令生成源码包,再执行rpm-bb命令生成执行码包。
选项列表
选项详解
通用选项的解释见<<精通RPM之二--安装篇>>,本文不再赘述。
1.--short-circuit:单步执行
此选项的目的在于单步执行功能段,仅适用命令为RPM-bc(或-tc)和-bi(或-ti)时。当用rpm-bc--short- circuit命令时,RPM将不再执行预处理段(%prep)的脚本程序,直接执行编译段(%build)的脚本程序。当用rpm-bi-- short-circuit命令时,RPM将不再执行预处理段(%prep)和编译段(%build)的脚本程序,仅执行安装段(%install)的脚 本程序。
为什么要使用这个选项?其原因可能是源程序包中的文件有问题,导致RPM在编译或安装过程中出现了这样或那样的错误,如不能单步执行,则无法排除 这些错误。单步执行后,用户可以进入源程序所在的目录,查看源程序,修改错误,然后再用tar命令生成一个正确的源程序包,覆盖掉原包即可。这样,RPM 再制作时就不会有问题了。
2.--timecheck:设置时间检查值
该选项的用法是:--timecheck<secs>
注:<secs>为检查的时间段,单位是秒,如--timecheck600设置检查的时间段为600秒,即10分钟。
设置时间检查值的目的,在于检验打包文件是否是指定时间段内产生的新文件,如果不是,则RPM会产生警告信息,提醒用户某个文件不是新文件,而是 老文件,可能是某种错误导致的。这种错误,可能是由于makefile(维护文件)或描述文件中的安装段脚本程序书写不正确,从而使某个程序不能正确安装 到指定目录,因而RPM打包时总是引用老的程序文件。如下面的例子:
#rpm-bl--timecheck600lze-6.0-2.spec
Processingfiles:lze
warning:TIMECHECKfailure:/usr/bin/lze
FindingProvides:(using/usr/lib/rpm/find-provides)...
FindingRequires:(using/usr/lib/rpm/find-requires)...
Provides:lze-edit
PreReq:/bin/sh
Requires:/bin/shld-linux.so.2libc.so.6libc.so.6(GLIBC_2.0)libc.so.6(GLIBC_2.1)
#
注:本例中利用RPM检查文件列表,看哪个文件是在10分钟以前产生的老文件,结果RPM发出警告信 息:“warning:TIMECHECKfailure:/usr/bin/lze”,这说明文件/usr/bin/lze时间检查出现错误,这是个老 文件。经查,是makefile的问题,里面少了一句“cplze/usr/bin”。修正后,再次编译连接程序,再进行时间检查就没有这个问题了。
3.--buildroot:设定建包用根目录
该选项的用法是:
--buildroot<dir>
注:<dir>为用户指定的建包用的根目录。
此选项相当于在软件包描述文件的文件头加上一行:
Buildroot:<dir>
只不过在命令行上设定比较自由罢了。
通过设定建包用根目录,一般用户也可以建立那些只有超级用户(root)才能建立的RPM包了。下面以普通用户zzz建立LZE软件包为例,说明一下这种形式的包的建立过程。
1)在用户zzz的HOME目录(/usr/zzz)下,建立RPM建包所用的目录:
$cd/usr/zzz
$mkdir-prpm/{BUILD,RPMS/i386,SOURCES,SPECS,SRPMS}
$
2)拷贝描述文件lze-6.0-2.spec到rpm/SPECS目录,拷贝源程序包lze-6.0-2.src.tgz到rpm/SOURCES目录。
$cd/usr/zzz
$cp/root/lze-6.0-2.specrpm/SPECS
$cp/root/lze-6.0-2.src.tgzrpm/SOURCES
$
3)建立.rpmmacros文件,编辑它:
$cd/usr/zzz
$vi.rpmmacros
在此文件中增加一行:
%_topdir/usr/zzz/rpm
用于确定RPM建包用的顶层目录为/usr/zzz/rpm。
4)转到描述文件目录,编辑修改lze-6.0-2.spec安装段的脚本程序:
$cd/usr/zzz/rpm/SPECS
$vilze-6.0-2.spec
$
用于确定RPM建包用的顶层目录为/usr/zzz/rpm。
安装段脚本程序修改为:(原make命令被注释掉)
%install
echo"安装脚本程序(install)开始执行"
#makeinstall
mkdir-p$RPM_BUILD_ROOT/usr/bin
mkdir-p$RPM_BUILD_ROOT/etc
mkdir-p$RPM_BUILD_ROOT/usr/doc/lze-6.0
cplzelzeime.wblzeime.py$RPM_BUILD_ROOT/usr/bin
cpinputme.deffunkey.defwbzc.dat$RPM_BUILD_ROOT/etc
cp/usr/doc/lze-6.0/*$RPM_BUILD_ROOT/usr/doc/lze-6.0
注:脚本程序中,使用建包用根目录的环境变量RPM_BUILD_ROOT,相继在建包用根目录下创建若干子目录 (usr/bin,etc,usr/doc/lze-6.0),然后拷贝程序或文件到相应的子目录中,从而完成完装。 5)选用--buildroot选项,执行RPM建包命令:
$cd/usr/zzz/rpm/SPECS
$rpm-bb--buildroot/usr/zzz/tmplze-6.0-2.spec
Executing:%prep
+umask022
+cd/usr/zzz/rpm/BUILD
+echo'预处理脚本程序(prep)开始执行'
预处理脚本程序(prep)开始执行
+cd/usr/zzz/rpm/BUILD
+rm-rflze-6.0
+/bin/gzip-dc/usr/zzz/rpm/SOURCES/lze-6.0-2.src.tgz
+tar-xvvf-
drwxr-xr-xroot/root02001-11-0217:04lze-6.0/
-rw-------root/root2462262001-11-0216:00lze-6.0/lze.c
-rw-------root/root982492001-11-0216:00lze-6.0/lzeime.wb.c
-rw-------root/root3399022001-11-0216:00lze-6.0/lzeime.py.c
-rw-r--r--root/root12832001-11-0216:00lze-6.0/funkey.def
-rwxr--r--root/root2502001-11-0216:00lze-6.0/inputme.def
-rw-r--r--root/root8132742001-11-0216:00lze-6.0/wbzc.dat
-rw-------root/root4742001-11-0216:02lze-6.0/makefile
-rw-r--r--root/root12552001-11-0217:04lze-6.0/getinputme.c
+STATUS=0
+'['0-ne0']'
+cdlze-6.0
++/usr/bin/id-u
+'['500=0']'
++/usr/bin/id-u
+'['500=0']'
+/bin/chmod-Rfa+rX,g-w,o-w.
+exit0
Executing:%build
+umask022
+cd/usr/zzz/rpm/BUILD
+cdlze-6.0
+echo'编译连接脚本程序(build)开始执行'
编译连接脚本程序(build)开始执行
+make
cc-fwritable-strings-DUSE_AS_LZE-DFOR_LINUX-s-I/usr/zzz/src/include-DFOR_LZE_INPUTME-olze/usr/zzz/src/libsrc/mycurses.clze.cgetinputme.c/usr/zzz/src/my.a
cc-DFOR_LINUX-s-I/usr/zzz/src/include-olzeime.wbgetinputme.clzeime.wb.c/usr/zzz/src/my.a
lzeime.wb.c:Infunction`do_service':
lzeime.wb.c:1409:warning:passingarg5of`bsearch'fromincompatiblepointertype
cc-DFOR_LINUX-s-I/usr/zzz/src/include-olzeime.pygetinputme.clzeime.py.c/usr/zzz/src/my.a
+exit0
Executing:%install
+umask022
+cd/usr/zzz/rpm/BUILD
+cdlze-6.0
+echo'安装脚本程序(install)开始执行'
安装脚本程序(install)开始执行
+mkdir-p/usr/zzz/tmp/usr/bin
+mkdir-p/usr/zzz/tmp/etc
+mkdir-p/usr/zzz/tmp/usr/doc/lze-6.0
+cplzelzeime.wblzeime.py/usr/zzz/tmp/usr/bin
+cpinputme.deffunkey.defwbzc.dat/usr/zzz/tmp/etc
+cp/usr/doc/lze-6.0/LICENSE/usr/doc/lze-6.0/README/usr/zzz/tmp/usr/doc/lze-6.0
+exit0
Processingfiles:lze
FindingProvides:(using/usr/lib/rpm/find-provides)...
FindingRequires:(using/usr/lib/rpm/find-requires)...
Provides:lze-edit
PreReq:/bin/sh
Requires:/bin/shld-linux.so.2libc.so.6libc.so.6(GLIBC_2.0)libc.so.6(GLIBC_2.1)
Wrote:/usr/zzz/rpm/RPMS/i386/lze-6.0-2.i386.rpm
Executing:%clean
+umask022
+cd/usr/zzz/rpm/BUILD
+cdlze-6.0
+echo'建包结束后清理脚本程序(clean)开始执行'
建包结束后清理脚本程序(clean)开始执行
+exit0
$
注:RPM建包成功后,生成了/usr/zzz/rpm/RPMS/i386/lze-6.0-2.i386.rpm包裹文件,
通过RPM的查询命令,我们就可以知道该包与由超级用户建成的包内容毫无二致:
$rpm-qplv/usr/zzz/rpm/RPMS/i386/lze-6.0-2.i386.rpm
-rw-r--r--rootroot128311月609:24/etc/funkey.def
-rwxr-xr-xrootroot25011月609:24/etc/inputme.def
-rw-r--r--rootroot81327411月609:24/etc/wbzc.dat
-rwxr-xr-xrootroot40863211月609:24/usr/bin/lze
-rwxr-xr-xrootroot8292011月609:24/usr/bin/lzeime.py
-rwxr-xr-xrootroot3856811月609:24/usr/bin/lzeime.wb
-rw-r--r--rootroot121511月609:24/usr/doc/lze-6.0/LICENSE
-rw-r--r--rootroot369011月609:24/usr/doc/lze-6.0/README
$
现在我们可以说,普通用户也可以自由地建立各种形式的RPM软件包了!
4.--target:设定目标平台
该选项的用法为:--target体系-平台-操作系统
注:RPM制作出来的软件包默认的体系为i386,平台为pc,操作系统为linux。如果用户想加以改变,就需要使用此选项来确定一下,如下例:
#rpm-bb--targeti686-pc-solaris--quietlze-6.0-2.spec
创建目标平台:i686-pc-solaris
正在创建目标:i686-pc-solaris
#
本例设定生成的RPM包适用的目标平台为:i686-pc-solaris(即体系为i686,平台为pc,操作系统为solaris)。注意: 必须在/usr/src/dist/RPMS目录下创建一个i686的子目录,没有指定体系的子目录,RPM将无法生成软件包。我们可以查询一下生成的软 件包,看其适用的体系与操作系统是什么:
#rpm-qp--qf"archis%{arch}nosis%{os}n"/usr/src/dist/RPMS/i686/lze-6.0-2.i686.rpm
archisi686
osissolaris
#
从输出上可以看到,其体系与操作系统正是我们所设定的。
5.--quiet:尽量减少信息输出
此选项的目的,是让RPM减少信息的输出。使用此选项后,如果没有错误发生,RPM就不会输出多余的信息,这时的RPM也显得比较“安静”(quiet)了。
$rpm-bl--quietlze-6.0-2.spec
$
6.--clean:执行文件清理
如果软件包描述文件的清理段(%clean)没有删除临时文件的命令,那么RPM建包结束后那些临时文件还是存在的,占用了一定的空间。如果想让RPM自动删除那些临时文件,可以在建包时使用--clean选项。此选项执行一条命令,即:
rm-rf软件名-版本号
用它来删除"软件名-版本号"目录及该目录下的所有文件。这个"软件名-版本号"目录,也即RPM默认的存放解压后的源程序的目录。
#rpm-bl--cleanlze-6.0-2.spec
Processingfiles:lze
FindingProvides:(using/usr/lib/rpm/find-provides)...
FindingRequires:(using/usr/lib/rpm/find-requires)...
Provides:lze-edit
PreReq:/bin/sh
Requires:/bin/shld-linux.so.2libc.so.6libc.so.6(GLIBC_2.0)libc.so.6(GLIBC_2.1)
Executing:--clean
+umask022
+cd/usr/src/dist/BUILD
+rm-rflze-6.0
+exit0
注:例中的“Executing:--clean”表示RPM开始执行自己的文件清理操作。
7.--rmsource:删除源程序及描述文件
此选项用于指示RPM在建包后删除软件源程序和包描述文件,软件源程序由包描述文件中的Source域定义。此选项也可单独使用,如:
#rpm--rmsourcelze-6.0-2.spec
#lslze-6.0-2.spec../SOURCES/lze-6.0-2.src.tgz
ls:lze-6.0-2.spec:文件或目录不存在
ls:../SOURCES/lze-6.0-2.src.tgz:文件或目录不存在
#
8.--sign:软件包内置数字签名
此选项用于在软件包内添加PGP数字签名,通过数字签名,用户可以校验软件包是否原装,是否修改过。要使用PGP数字签名,必须先安装好PGP应用程序及产生自己的密钥对。(有关数字签名的内容,详见<<精通RPM之八--签名篇>>)
使用此选项建包时,RPM会要求输入密码,验证正确后开始执行建包的系列操作,在建包前会产生数字签名,以便写入包中。请看下例:(省略不少输出,......表示)
#rpm-bb--signlze-6.0-2.spec
Enterpassphrase:mypass
Passphraseisgood.
Executing:%prep
......
Executing:%build
......
Executing:%install
......
Processingfiles:lze
......
Requires:/bin/shld-linux.so.2libc.so.6
Generatingsignature:1002
GeneratingsignatureusingPGP.
PrettyGoodPrivacy(tm)Version6.5.8
(c)1999NetworkAssociatesInc.
UsestheRSAREF(tm)Toolkit,whichiscopyrightRSADataSecurity,Inc.
ExportofthissoftwaremayberestrictedbytheU.S.government. Wrote:/root/test/RPMS/i386/lze-6.0-2.i386.rpm
Executing:%clean
......
#
注:例中要求输入密码,输入mypass后校验成功,之后RPM开始建包操作。(实际上,mypass在屏幕上并不显示出来)例中的Generatingsignature之下的几行就是产生数字签名时输出的东西。
其它建包相关的命令
其它建包相关的命令有两个,它们都是针对RPM格式的源码包进行操作的,执行时先安装源码包,然后再根据软件包描述文件进行下一步的工作。 1.重编译命令:
用法为:rpm--recompileRPM源码包1RPM源码包2...
如:
rpm--recompilelze-6.0-2.src.rpm
此命令执行时,首先安装此源码包,然后依次执行源码包内软件包描述文件的预处理段(%prep),编译段(%build),安装段(%install)的脚本程序。此命令相当于以下两条命令:
1)rpm-ilze-6.0-2.src.rpm
2)rpm-bilze-6.0-2.spec
2.重建立命令:
用法为:rpm--rebuildRPM源码包1RPM源码包2...
如:
rpm--rebuildlze-6.0-2.src.rpm
重编译命令执行后并不建立新的RPM软件包,而此重建立命令执行后则会制作出一个新的RPM软件包。重建立命令执行时,首先安装RPM源码包,然 后依次执行源码包内软件包描述文件的预处理段(%prep),编译段(%build),安装段(%install),清理段(%clean)的脚本程序, 生成一个新的RPM执行包,最后删除源程序包,描述文件及其它临时文件。此命令相当于以下两条命令:
1)rpm-ilze-6.0-2.src.rpm
2)rpm-bb--clean--resourcelze-6.0-2.spec
------------
RPM的另类用法
RPM不仅在安装,升级,卸载方面工作出色,而且在查询方面比其它软件包管理工具更胜一筹。这从以下几种情况可以看出:
* 当你在浏览系统文件时,发现一个文件,想知道它来自哪个软件包时,可以用RPM来查询得知;
* 当你的朋友给你发送来一个软件包,但你不知道这是个什么样的软件包,不知道它做些什么,安装些什么,来源是哪里。这时,你可以用RPM查询搞定;
* 几个月前你安装了XFree86窗口软件,但现在你忘了它的版本号,也不知它的说明文档在哪里。这时,你可以用RPM查询一下这个软件包,得到这方面的信息。
RPM的查询还有一个高级功能,即定制输出功能。你可用--queryformat(或-qf)来定制一下输出格式,这样,RPM查询得到的信息将以你定制的格式输出,这样很是方便,尤适合于程序的自动处理。
命令格式
查询RPM格式的软件包,可使用如下命令格式:
rpm -q [查询选项1 查询选项2...]
注: 也可使用--query代替-q,效果相同。
选项列表
选项详解
指定用选项中ftp与http相关的四个选项(--ftpproxy,--ftpport,--httpproxy,--httpport)和通用选项的解释,请参见<<精通RPM之二--安装篇>>,本文不再赘述。下面对指定用选项做些解释:
指定用选项可分为如下几类:
一、软件包选择类
此类选项在一次只能选择一个,选择多个时RPM将提示错误:
rpm: one type of query/verify may be performed at a time
从查询方面看,一个是查询那些已安装的软件包,一个是查询未安装的软件包。
1. 查询已安装的软件包,使用下列选项:
(1) -a (或--all) : 查询所有已安装的软件包
# rpm -q -a
setup-2.0.2-1
filesystem-1.3.4-5
basesystem-6.0-5
agrep-2.04-5
aktion-0.3.6-2
amor-0.5-1
dhcpcd-1.3.17pl2-1
ldconfig-1.9.5-15
glibc-2.1.2-12
chkconfig-1.0.6-2
......
#
注: 本例查找当前系统中安装的所有软件包,输出很多,仅列出几个,剩下的省略掉了(以......表示)。
(2) -g (或--group) : 查询有哪些软件包属于指定类别
RPM根据软件功用的不同,将软件分为以下若干类:(括号内为注释)
Amusements/Games (娱乐/游戏)
Amusements/Graphics(娱乐/图形)
Applications/Archiving (应用/档案)
Applications/Communications (应用/通讯)
Applications/Databases (应用/数据库)
Applications/Editors (应用/编辑器)
Applications/Emulators (应用/仿真器)
Applications/Engineering (应用/工程)
Applications/File (应用/文件)
Applications/Internet (应用/因特网)
Applications/Multimedia (应用/多媒体)
Applications/Productivity (应用/产品)
Applications/Publishing (应用/印刷)
Applications/System (应用/系统)
Applications/Text (应用/文本)
Development/Debuggers (开发/调试器)
Development/Languages (开发/语言)
Development/Libraries (开发/函数库)
Development/System (开发/系统)
Development/Tools (开发/工具)
Documentation (说明文档)
System Environment/Base (系统环境/基础)
System Environment/Daemons (系统环境/守护)
System Environment/Kernel (系统环境/内核)
System Environment/Libraries (系统环境/函数库)
System Environment/Shells (系统环境/接口)
User Interface/Desktops (用户界面/桌面)
User Interface/X (用户界面/X窗口)
User Interface/X Hardware Support (用户界面/X硬件支持)
Other (其它)
注意: 类别是大小写敏感的,这一点输入时要小心。如果用户想要查询当前系统安装了哪些游戏类的软件包,可这样做:
# rpm -q -g Amusements/Games
clanbomber-1.01-1
kdegames-1.1.2-1
xbill-2.0-6
xboard-4.0.0-3
xboing-2.4-7
xgammon-0.98-14
xjewel-1.6-11
xpat2-1.04-10
xpilot-3.6.2-6
xpuzzles-5.4.1-7
xtrojka-1.2.3-6
#
如果用户想查询若干类别的软件包时,可以把类别都列出来,一起查询,如:
# rpm -q -g Applications/Editors Applications/File
emacs-20.3-15
emacs-nox-20.3-15
emacs-X11-20.3-15
vim-common-5.6-12
vim-minimal-5.6-12
vim-X11-5.6-12
fileutils-4.0-3
bzip2-0.9.5d-1
findutils-4.1-32
git-4.3.17-6
gzip-1.2.4-15
slocate-1.4-7
stat-1.5-12
file-3.26-6
#
注: 本例查询结果中前6个为"应用/编辑器"类别,后8个为"应用/文件"类别。
(3) -f (或--file) : 查询有哪些软件包拥有指定文件这个选项非常有用。当用户不清楚某个文件属于哪个软件包时,可试试这个选项。假如我记不清/usr/sbin/ftpd这个文件在哪个包中,现在用RPM查询:
# rpm -qf /usr/sbin/ftpd
inet6-apps-0.36-3
#
现在知道了,它在inet6-apps-0.36-3包中。命令中-qf是-q -f的缩写,当选项仅带一个减号时,多个选项可以合并在一起,如-a -b -c三个选项可写作-abc,执行效果相同。
(4) --whatrequires : 查询有哪些包需要指定功能
本选项指示RPM从所有已安装的软件包中,查询有哪些软件包提供了用户指定的功能,命令行上可输入一个或多个功能。
# rpm -q --whatrequires /bin/ps libc.so.6 | head
autofs-3.1.3-2
agrep-2.04-5
aktion-0.3.6-2
amor-0.5-1
chkconfig-1.0.6-2
libtermcap-2.0.8-16
bash-2.03-10
ncurses-4.2-18
info-3.12f-4
fileutils-4.0-3
#
注: 本例从系统中查询哪些软件包需要/bin/ps和libc.so.6功能,通过管道输出前10行内容。
(5) --whatprovides : 查询有哪些包提供指定功能
本选项指示RPM从所有已安装的软件包中,查询有哪些软件包提供了用户指定的功能。命令行上可输入一个或多个功能。
# rpm -q --whatprovides libc.so.6 /bin/ps
glibc-2.1.2-12
no package provides /bin/ps
#
注: 本例从系统中查询有哪些软件包提供libc.so.6与/bin/ps功能,结果是glibc-2.1.2-12包提供了libc.so.6,而没有包提供/bin/ps功能。
( 6) --triggeredby : 查询有哪些包被指定的包触发本选项指示RPM从所有已安装的软件包中,查询有哪些包可被用户指定的包触发。指定的包可输入一个或多个。
# rpm -q --triggeredby file
foo-8.0-1
#
注: 本例查询后得知,安装或卸载foo-8.0-1包,将会触发与file包相关的脚本程序执行。
2. 查询未安装的软件包: (仅有一个选项可用)
(1) -p : 查询指定包裹文件的信息
使用本选项,通过指定一个或多个包裹文件名,RPM就可以获取相应包裹的有关信息。包裹文件可以是一般形式,也可是ftp/http形式。
# rpm -qp -l --ftpport 2121 ftp://zzz:pass@linux/zhsoft/file-3.26-6.i386.rpm
/usr/bin/file
/usr/man/man1/file.1
/usr/man/man4/magic.4
/usr/share/magic
#
注: 本例查询ftp形式的包裹,显示其文件列表(-l选项使然,下面要讲到)。ftp用户名zzz,密码为pass,远程机为linux,文件名为/zhsoft/file-3.26-6.i386.rpm,ftp使用2121端口。
二、信息显示类
本类选项可同时选择多个,以显示多种信息。
1. -i : 显示软件包信息
当用户需要了解软件包的头部信息时,要使用该选项。
# rpm -qi file
Name: file Relocations: /usr
Version : 3.26 Vendor: Red Hat Software
Release : 6 Build Date: 1999年03月23日 星期二 05时32分29秒
Install date: 2001年10月14日 星期日 21时18分25秒 Build Host: porky.devel.redhat.com
Group : Applications/File Source RPM: file-3.26-6.src.rpm
Size: 211946 License: distributable
Packager: Red Hat Software
Summary : A utility for determining file types.
Description :
The file command is used to identify a particular file according to the
type of data contained by the file. File can identify many different
file types, including ELF binaries, system libraries, RPM packages, and
different graphics formats.
You should install the file package, since the file command is such a
useful utility.
#
上述输出中,包含多个域,各个域的含义为:
Name : 软件名;Relocations : 重定位目录前缀(一个或多个);
Version : 版本号;Vendor : 开发商;
Release : 释出号;Build Date : 包建立时间;
Install date : 安装时间; Build host : 包建立主机;
Group: 类别; Source RPM : 源代码包;
Size : 大小; License : 许可证;
Packager : 打包者;
Summary : 软件简介;
Description : 详细描述。
2. -l (或--list) : 显示软件包文件列表
当用户想知道软件包包含哪些文件时,要使用该选项。输出时,一行一个文件名,形成文
件列表。下例列出file包中文件:
# rpm -qlv file
-rwxr-xr-x root root23948 3月 23 1999 /usr/bin/file
-rwxr-xr-x root root12023 3月 23 1999 /usr/man/man1/file.1
-rwxr-xr-x root root 6625 3月 23 1999 /usr/man/man4/magic.4
-rwxr-xr-x root root 169350 3月 23 1999 /usr/share/magic
#
注: 本例列文件时选用了通用选项-v,这样列出的格式同ls命令列出的格式,从中可以看到各个文件的权限,属主,属组,大小,最后修改时间及文件名等信息。
3. -d (或--docfiles) : 显示软件包说明文档RPM将软件包中的文件分为三类,一是配置文件,一是说明文档,再一是其它文件(包括可执行程序及数据文件等)。通过-d选项,可列出包中所有说明文档。下例列出file包中说明文档:
# rpm -qd file
/usr/man/man1/file.1
/usr/man/man4/magic.4
#
4. -c (或--configfiles) : 显示软件包配置文件使用本选项可列出包中所有配置文件。下例列出lze包中的配置文件:
# rpm -qc lze
/etc/funkey.def
/etc/inputme.def
#
5. -s (或--state) : 显示软件包文件状态RPM已安装的软件包中各个文件可拥有如下4种状态:
* normal(正常): 这表明文件未被其它软件包修改过。
* replaced(已替换): 这表明文件已被其它软件包修改替换过了,不再是原先的文件了。* not installed(未安装): 这表明文件未安装。有一种原因可导致这种情况发生,这就是当安装软件包时使用了--excludedocs选项(或是通过设置%_excludedocs 宏为1),说明文档未被安装到系统中。当用RPM查询此软件包状态时,所有说明文档均显示此状态。
* net shared(网络共享): 这表明文件处于网络共享状态。这一状态是RPM用来支持NFS(网络文件系统)的,用于避免一个NFS客户端系统删除一个正在共享的文件时,另一NFS客 户端系统无法正常使用含此文件的软件包。有两种情况可使文件在此状态,一是文件安装在真实网络共享的目录里,二是文件安装在RPM资源配置文件 中%_netsharedpath宏所确定的目录里。
# rpm -i --excludedocs file-3.26-6.i386.rpm
# rpm -qs file
normal/usr/bin/file
not installed /usr/man/man1/file.1
not installed /usr/man/man4/magic.4
normal/usr/share/magic
#
注: 本例先安装file包裹文件,选用--excludedocs表明不安装说明文档。而后再查询file包文件的状态,可以看到其说明文档均为not installed(未安装),其它文件为normal(正常)状态。
6. -R (或--requires) : 显示软件包所需的功能
所谓功能,可以是软件包标识,可以是文件(如共享库libc.so.6等),也可以是虚拟的名字。软件包的依赖关系,就是依靠功能来实现的。RPM安装软件包时,如果所需功能不存在,则其依赖关系不满足,RPM将中断安装过程。
# rpm -q -R lze
/bin/sh
ld-linux.so.2
libc.so.6
libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1)
#
注: 本例查询lze包所需的功能。
7. --provides : 显示软件包提供的功能
一个软件包,可以提供若干功能,这些功能可以是动态链接库等实际的文件,也可以是虚拟的名字(只要其它软件包可以用就行了)。如果想查询某个包提供了哪些功能,要用--provides
选项。
下面的例子查询一个包裹文件所提供的功能:
# rpm -qp --provides zlib-1.1.3-6.i386.rpm
libz.so.1
libz.so.1(GCC.INTERNAL)
#
注: 本包裹文件提供的功能是libz.so.1动态链接库。
8. --conflicts : 显示软件包冲突的功能
何谓冲突?冲突就是不同软件包之间不能共存的现象。RPM制作软件包时,可以记录下与本软件包不能共存的功能,这样安装该包时,若冲突的功能已然存在,则RPM将中止安装。
下面的例子查询at-3.1.7-8包是否有与其冲突的功能:
# rpm -q --conflicts at-3.1.7-8
crontabs <= 1.5
#
注: 本例显示at包与版本号小于1.5的crontabs包有冲突存在。
9. --scripts : 显示软件包内置的脚本程序
scripts即脚本,指的是用SHELL语言编写的程序。选用本选项时,RPM将输出软件包所含的各类脚本程序的内容。总共有5类这样的脚本程 序,即安装前脚本程序(preinstall),安装后脚本程序(postinstall),卸载前脚本程序(preuninstall),卸载后脚本程 序(postuninstall)和校验脚本程序(verify)。
下面的例子列出zsh包的脚本程序:
# rpm -q --scripts zsh-3.0.7-4 | nl
1 postinstall script (through /bin/sh):
2 if [ ! -f /etc/shells ] ; then
3 echo "/bin/zsh" > /etc/shells
4 else
5 echo "/bin/zsh" >> /etc/shells
6 fi
7 /sbin/install-info /usr/info/zsh.info.gz /usr/info/dir
8 --entry="* zsh: (zsh). An enhanced bourne shell."
9 preuninstall script (through /bin/sh):
10 if [ "$1" = 0 ] ; then
11 /sbin/install-info --delete /usr/info/zsh.info.gz /usr/info/dir
12 --entry="* zsh: (zsh). An enhanced bourne shell."
13 fi
14 postuninstall script (through /bin/sh):
15 if [ "$1" = 0 ] ; then
16 if [ -f /etc/shells ] ; then
17 TmpFile=`/bin/mktemp /tmp/.zshrpmXXXXXX`
18 grep -v '^/bin/zsh$' /etc/shells > $TmpFile
19 cp -f $TmpFile /etc/shells
20 rm -f $TmpFile
21 chmod 644 /etc/shells
22 fi
23 fi
#
注: 本例利用管道技术给查询的每行输出加上了行号,便于观察解释。
第2-8行: 为安装后脚本程序(postinstall)的源代码;
第10-13行: 为卸载前脚本程序(preuninstall)的源代码;
第15-23行: 为卸载后脚本程序(postuninstall)的源代码。
例中所有脚本程序均通过/bin/sh解释执行,本例没有安装前脚本程序(preinstall)和
校验脚本程序(verify)。
10. --triggers : 显示软件包内置的触发脚本程序
触发脚本程序是scripts类脚本程序的扩展,它用于软件包之间的交互控制。触发脚本
程序有安装时触发脚本程序(triggerin),卸载前触发脚本程序(triggerun)和卸载后触发脚
本程序(triggerpostun)三种。
下面的例子列出zsh包中的触发脚本程序:
# rpm -q --triggers zsh-3.0.7-4
triggerpostun script (through /bin/sh) -- zsh <= 3.0.7-2
if [ ! -f /etc/shells ] ; then
echo "/bin/zsh" > /etc/shells
else
echo "/bin/zsh" >> /etc/shells
fi
#
注: 输出的第1行说明脚本程序的类别(为卸载后触发脚本程序triggerpostun),用什么程序解释(一般为/bin/sh),和触发的条件(在--之 后描述)。本例的触发条件为zsh的版本小于或等于3.0.7-2。如果条件成立,则此脚本程序将会执行。 输出的第2-6行为卸载后触发脚本程序的源代码。
11. --changelog : 显示软件维护记录
changelog即软件维护记录,用它来记录什么人,什么时间,改动了软件的什么地方。通
过查看维护记录,开发者或用户可以了解软件的开发进展情况。
下面的例子查询lze包的维护情况:
# rpm -q --changelog lze-6.0-2
* 五 5月 01 1998 雨亦奇
- 增加多窗口操作
* 一 3月 24 1997 雨亦奇
- 增加块操作命令
#
注: 从本例中就可以看出来,维护记录的书写有一定的规范:以星号(*)开头的行记录维护时间,维护人及其电子邮箱,而以减号(-)开头的行则记录维护的具体内容。
12. --dump : 显示软件包中所有文件的属性信息
如果用户想查看某个软件包内文件的属性信息,请用--dump选项。
# rpm -q --dump file
/usr/bin/file 23948 922138347 abaf6cfd51588ac7c484526fbdb84e5b 0100755 root root 0 0 0 X
/usr/man/man1/file.1 12023 922138346 76d9ff6567ab64a53eab50911272f5c1 0100755 root root 0 1 0 X
/usr/man/man4/magic.4 6625 922138346 b8d126803709f0da7f39f5125a132cd3 0100755root root 0 1 0 X
/usr/share/magic 169350 922138346 3bd2eaf3c5e0e84153ba7df38b7561fc 0100755 root root 0 0 0 X
#
现在根据例子的输出,解释一下RPM包中各个文件所拥有的属性信息:(以第1行为例)
/usr/bin/file : 为文件名;
23948 : 指文件大小(字节数);
922138347 : 指文件最后修改时间(秒数);
abaf6cfd51588ac7c484526fbdb84e5b : 指根据文件内容计算出的MD5检查和;
0100755 : 指文件存取权限;
root : 指文件属主;
root : 指文件属组;
0 : 配置文件标志,为0表示该文件非配置文件,为1表明该文件是配置文件;
0 : 说明文档标志,为0表示该文件非说明文档,为1表明该文件是说明文档;
0 : 指文件类型,为0表示普通文件,非0表示设备文件,包含主从设备号;
全文结束