Guru Labs《Creating RPMs (Student version)》v1.0 (创建 RPM 打包,学生版)
来源:百度文库 编辑:神马文学网 时间:2024/04/30 01:02:15
Guru Labs《Creating RPMs (Student version)》v1.0 (创建 RPM 打包,学生版)
Page 0
Guru Labs
《Creating RPMs (Student version)》v1.0 (创建 RPM 打包,学生版)
本文目的 1. 作为我们的教学课件的范例用于评估 2. 为系统管理员提供高质量的 RPM 手册
有关本教程 您看到的蓝色背景,模拟了印刷 Guru Labs 课件所用的自定义纸张。学生版不包括教师版中的指令备注和教学提示。
有关我们特别的排版信息,参见 http://www.gurulabs.com/courseware/c...are_layout.php
有关我们提供的免费教学内容,包括本文的最新版,参见 http://www.gurulabs.com/goodies/
范例在以下平台中得到验证 rhel4, fc3, suse9, suse9.2
关于 Guru Labs
Guru Labs 是一个 Linux 培训公司,由 Linux 专家创建于 1999,提供最好的 Linux 培训和课件。全面的内容请参见 http://www.gurulabs.com
Copyright Guru Labs, L.C. 2005
Licensed under the Creative Commons Attribution-NonCommercial-NoDerivs License. http://creativecommons.org/licenses/by-nc-nd/2.0 (译文违反了许可,但是我想这份许可的 -nd- 是由于采用了特殊的背景和排版,而不是因为翻译能涉及到的那些 (应当) 人所共知的知识?)
Guru Labs 801 N 500 W Ste 202 Bountiful, UT 84010 Ph: 801-298-5227
WWW.GURULABS.COM
Page 1
目标
* 理解 UNIX/Linux 软件管理的历史概况
* 描述 RPM 系统的特点与结构
* RPM 的日常应用,各种不同的 RPM 打包的处理
* 修改并重构建已有的 SRPMS
* 学习 RPM SPEC 文件的语法,以及编译基础要求
* 创建新的 SPEC 文件,辅助文件以及 RPM 文件
* 高级的 RPM 创建技术
* 处理 Redhat 与 SuSE 发行版中,RPM 系统的不同之处
Page 2
处理打包
Unix 打包 (System V packages)
Linux 打包 (Slackware Tarballs, RPMs, Debian DPKGs)
传统上,UNIX 系统的软件都是以源代码形式发布的。要使用某个软件,管理员必须为要运行它的系统适当地编译它,然后安装它。如果它要求任何辅助的软件包, 那么也必须同时安装。如果要求本地进行任何定制,那么就必须去配置。
如果软件需要升级,管理员必须找到系统中, 属于这个软件的所有文件,替换为升级的版本,小心地保留那些本地作出的配置修改。
现在,考虑一个典型的 UNIX 工作站应用程序,例如 Mozilla。基本的 Mozilla 应用程序包含大约 495 个文件,分布在大约 10 个不同的目录中。在删除时,管理员必须找到所有这些文件并且删除。在升级时,管理员必须手工地替换所有文件。在运行时,Mozilla 要求安装大约 50 种其他可执行文件和运行时库 (而这些又会依赖于其他库文件)。
手工管理所有这些不是不可能的, 并且 Unix 管理员已经这样做了三十多年了,不过,很多服务提供商开发了简化此类工作的工具。在商业 Unix 世界中,System V Unix 定义了一种标准“打包”系统,这成为了此类软件的基础,包括 Solaris 中使用的 pkg 格式,还有 HP-UX 中使用的 depot 格式。这些软件包系统提供了各种工具,可以用来安装、卸载和升级打包中的软件。打包中包含了软件和元数据 (例如列举出为了使软件可以运作,必须安装的其他软件等等)。
在 Linux 世界中,最初的软件没有打包,与 Unix 世界中完全相同。后来,在 1993 年 Slackware 发行版出现时,它引进了一种很初级的打包格式。之后,两种新的发行版,Redhat 与 Debian,都开始为 Linux 开发更多功能的打包软件。Debian 引进了 DPKG 打包系统,而 Redhat 引进了 RPM 打包系统。从那时开始, RPM 打包系统成为了 Linux 社区中的事实标准。它为几乎所有著名商业 Linux 发行版所用,包括来自 Redhat, SuSE 和 Mandrake 的那些。RPM 也是 Linux 世界中软件包管理的法律标准, Linux 标准化组织 LSB (Linux Standards Base) 要求相容于 LSB 的系统支持 RPM 文件的安装。
Page 3
RPM 特性
非交互安装,可运行脚本,可追踪/校验/查询已安装的文件,可追踪依赖性关系,可追踪整个源代码和编译过程,数字签名
RPM, RPM 包管理工具,提供了各种特性,使之成为 Linux 社区中杰出的包管理工具,大大简化了 Linux 管理员的工作。
RPM 提供了一系列的工具,可以用来实现非交互地,可运行脚本的安装过程。当软件安装之后,RPM 提供的工具可以用来追踪已安装的文件,使得卸载和升级非常简单,管理员可以检查软件安装是否正确,已安装的文件是否被修改过。另外,RPM 提供了一系列工具,可以用来查找已安装的文件,判断哪些程序在使用它们。
RPM 有杰出的依赖性追踪能力,意味着在安装新软件包时,它可以保证为了运行新软件,所有必需的软件都已经安装。在卸载软件时,它可以首先检测操作是否会影响其他应用程序。
另外,RPM 提供了一系列工具,管理从打补丁、配置直到编译的整个过程。当编译一个软件时,RPM 可以从原始的源代码开始,生成所需的补丁,将打补丁,配置源代码和编译源代码以产生可执行文件的过程脚本化。RPM 的这种功能极大地简化了企业中自定义软件的维护过程。
最后,RPM 允许将所有已打包的软件签名,使用公钥技术。这种特性允许验证 RPM 的可靠性,防止安装木马程序。
Page 4
RPM 结构
RPM 打包文件,数据库 /var/lib/rpm,工具 rpm,rpmbuild,rpmsign,rpm2cpio,RPM 配置文件 宏
RPM 系统包含多个组件。要使用 RPM 安装的软件必须打包成特定的格式,RPM 打包文件。RPM 打包文件是一个存档文件,包含了要安装的文件,以及元数据。RPM 系统使用元数据来保证将文件以正确的权限和所有者,安装到正确的位置。
在使用 RPM 安装软件时,软件名称和其他一些属性被记录到 RPM 数据库中,通常数据库在 /var/lib/rpm 目录。数据库包含了已安装程序的列表,以及属于这些软件的文件,使得以后可以方便地卸载或升级软件。它也记载了文件的属性,包括文件的大小,时间戳,校验和——保证可以在以后检测文件的正确性。数据库也包含了每个程序的依赖性信息,保证管理员安装软件时,所需的软件都已安装,卸载软件时,不会破坏其他现有的程序。
RPM 还包括一些工具。大多数 RPM 管理任务中,最基本的工具是 /bin/rpm 命令。在年代久远的系统中,如果用的是旧版本的 RPM,那么就只有这一个命令。在稍微新一些的系统中,新版本的 RPM 将过去 /bin/rpm 的许多功能移动到了辅助工具中。例如,/usr/bin/rpmbuild 命令用来生成新的 RPM 打包文件,/usr/bin/rpmsign 命令用来签署打包。
/usr/bin/rpm2cpio 命令一直都有,用来将一个 RPM 打包文件转换成标准的归档文件格式。
RPM 还有很多配置文件。在 rhel/fc 中,这些文件在 /etc/rpm 和 /usr/lib/rpm 目录,在 SuSE 中,这些文件只在 /usr/lib/rpm 目录。这些配置文件主要定义了宏——运行 RPM 命令或解析 RPM 打包文件时使用的快捷命令。
Page 5
RPM 打包文件
命名约定 体系结构 格式
要使用 RPM 安装的软件必须打包成 RPM 格式的文件。文件名应当有以下的格式:
名称-版本-发行标记.体系结构.rpm
在这个文件名中,名称表示包含在文件中的软件名,通常是软件的名字。版本表示软件的版本。尽管 RPM 文件格式以及工具没有强制要求,还是应当使用数字来表示版本。在这里使用字母会给很多 RPM 的前端带来问题。
发行标记用来表示对某个版本的打包的修正。有时,在为某个应用程序的某个版本制作 RPM 时会出错。这时,可以制作相同版本的修正了错误的新的 RPM。发行标记用来追踪打包文件的修正。这里也应该是一个数字,并且每次打包被修正后都应递增。
体系结构是这个 RPM 可以安装的系统平台。典型的值可以是:
* i386 任何 32 位 x86 系列 CPU
* i686 任何 686 级别的 32 位 x86 系列 CPU
* ppc64 64 位 PowerPC CPU
* x86_64 AMD 或 Intel 64 位 CPU
* ia64 64 位安腾 CPU
* sparc64 64 位 UltraSparc CPU
除了二进制可执行文件,RPM 还可以用来打包独立于平台的可执行程序 (例如使用解释性语言编写的程序,如 Lips, Perl 或 Java)。如果 RPM 包含的代码可以在任何 CPU 中运行,或者包含文档等独立于平台的文件,那么体系结构通常是 noarch
RPM 打包文件也可以用来打包应用程序源代码,补丁和用来指示如何配置和编译源代码的脚本。这些打包文件的体系结构使用 src,表示它们包含源代码而不是可执行文件。
如果 RPM 用作打包应用程序源代码,但是事实上不包括源代码的原始文件,只在元数据中保留了对源代码的引用,那么体系结构应当使用 nosrc,表示它们实际上没有打包源代码,但是可以像 src.rpm 一样使用。
不考虑它们的名字差别,所有 RPM 打包文件都是一个 cpio 归档文件,附加一个二进制的头部。
Page 6
使用 RPM
安装 升级 删除 查询/校验软件包/文件 rpm -iUFeqV
RPM 打包文件在安装时通常使用 rpm 命令和 -U 参数。通常,还要加上 -v 选项,使得 rpm 输出更多信息,还会加上 -h 选项,使得 rpm 执行时显示进度条
如果想安装一个软件包,同时还保留旧版本 (只有当两个版本中没有相同的文件时才可能做到),那么使用 -i 参数。通常在安装内核时会这样做,为了防止新内核出错,将旧内核保留下来。
也可以用 -F 参数来升级软件包 (通常,还要加上 -v 和 -h 选项),这个参数使得已安装的旧软件包得到更新,但是如果没有安装过,那么就不会安装它。
在进行升级或更新时,rpm 工具比较要安装的 RPM 版本与系统 RPM 数据库中,已安装的版本。如果要安装的软件包版本比已安装的版本更新,那么就升级。如果相反,那么 RPM 拒绝降级。如果版本号相同,RPM 就比较发行标记,只有当新打包的发行标记比已安装的打包的发行标记要新, 才进行升级。
软件包安装之后,可以用 -e 参数来删除
在删除软件包的时候,只要给出软件包的名称。在安装新软件包或者升级时,必须指定打包的全名。
打包文件和已安装的打包都可以查询。rpmquery 命令,或者 rpm 命令加上 -q 参数,都可以做很多查询。类似的,已安装的软件可以用 rpmverify 命令,或者 rpm 命令加上 -V 参数来校验。
Page 7
源代码 RPM 文件
原始源文件 补丁 辅助文件 脚本 .spec
rpm 命令可以用来处理源代码 RPM 文件 (SRPMs)。SRPMs 打包是用来构建作为最终产品安装到系统中的二进制 RPMs 打包的,如 .i386.rpm 和 .noarch.rpm 等等。SRPMs 包含几种不同的文件:
* 程序的最初的源文件
* 任何修改源程序的补丁
* 任何辅助的文件,例如 System V 启动脚本
* 指明如何配置和编译源代码的脚本。脚本通常命名为 name.spec,其中 name 是软件名
RPM 背后的一条设计原则是,软件包应当总是从最初的源代码编译。这一规则对于 Linux 社区很重要,每个程序都是由互联网上的松散的组织开发出来的,然后被 Redhat 和 SuSE 这样的发行版销售商整理到一起,成为一个集成的操作系统。发行版销售商经常需要修改源代码,使之可以更好地集成到发行版中,同样,最终用户也经常需要重新编译,有时需要打补丁,使得销售商提供的应用程序可以更好地适应自己的环境。从最初的源代码开始制作 RPM,加上各自的补丁,有助于简化长期的管理。这也使得最终用户可以容易地发现软件包作出了哪些修改。
通常,支持创建 RPM 的应用程序开发者会发布 SRPMs。不过有些开发者会仅仅发布标准的 Unix tar 打包格式的源代码,在其中包含一个 .spec 文件,指明如何从源代码编译生成一个二进制 RPM。
Page 8
使用源代码 RPMs
重新构建 创建
尽管管理员总是可以找到他们要安装的软件的二进制 RPMs,一些时候他们还是需要编译。有很多从源代码编译的理由:
* 发行版中未包含此软件
* 需要更新软件版本
* 需要以与发行版中的版本不同的选项和特性来编译应用程序
* 需要修正发行版中的版本包含的错误
在从源代码编译时,管理员仍然希望从 RPM 之类的包管理系统中得到便利,包括可以将来轻松地卸载,还有需要的时候升级等等。类似的,管理员在使用 RPM 工具编译时也会得到好处,包括内在的对构建命令的追踪,以及对补丁的取舍。
由于这些原因,管理员会选择从 SRPM 编译生成 RPMs。要生成二进制 RPM,管理员首先需要源代码 RPM,包含了用于生成二进制 RPM 的源代码。管理员通常有两种办法来获得 SRPM:
* 从头创建一个 SRPM
* 使用现有的 SRPM
当使用现有的 SRPM 时,管理员可以原样使用它,也可以进行定制。所有的操作都可以用 RPM 工具完成。
Page 9
准备构建
安装必需的软件 准备非 root 的构建环境
在从 SRPMs 构建 RPMs 的时候,首先需要进行准备工作。编译时需要的软件必须安装在用于构建的机器上。通常,这一需求意味着一般的开发工具,例如 gcc C 编译器以及 make 命令必须安装。与 Linux 发行版的安装方式相关,这些工具可能已经安装了,也可能没有。除了开发工具之外,很多软件包含编译期依赖关系,在编译时必须满足。很多应用程序要求在编译时必须能找到支持库和头文件,如果没有的话必须也安装它们。
二进制文件,一旦被编译,那么就可以在与它被编译的系统中,拥有相同的库文件的系统中顺利执行。因此,最好在与安装的目标系统相同的操作系统中编译它。
在从 SRPMs 构建 RPMs 的时候,尽可能使用非 root 用户,这非常重要。作为 RPM 构建过程的一步,RPM 工具将编译好的软件安装到一个虚拟的文件系统环境中。如果控制 RPM 构建过程的 spec 文件出错,可能导致 RPM 安装到真实的文件系统中。使用非 root 用户构建 RPM,尽管不是总是可行,但是防止了偶然的写入真实文件系统的事故,因为非 root 用户通常对 RPM 在安装时试图写入的目录没有写权限。
在当前的 SuSE 发行版中,RPMs 被配置为支持非 root 用户在 /usr/src/packages 子目录构建 RPM。在 Redhat 发行版中,必须进行配置,才能支持非 root 用户的构建。
要在 Redhat 发行版中配置普通用户构建 RPM:
1. 作为要执行构建的非特权用户登录
2. 创建 RPM 构建所需的目录结构
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,S{OURCE,PEC,RPM}S}
或者
$ cp -a /usr/src/redhat ~/rpmbuild
3. 配置 RPM 在构建时使用新的目录结构,而不是默认的目录结构:
$ echo "%_topdir $HOME/rpmbuild" > ~/.rpmmacros
在执行了这些命令之后,RPM 将会在用户的个人目录下 rpmbuild 目录中构建。要在其他位置构建 RPMs,只要调整路径为合适的值。
Page 10
重构建现有的打包
源代码 RPMs
包含 .spec 文件的 tar 打包
准备好合适的编译环境之后,就可以重建现有的打包了。在较新的系统中,命令:
$ rpmbuild --rebuild name-ver-rel.src.rpm
可以用来编译 SRPMs 生成二进制 RPM,而命令
$ rpmbuild --recompile name-ver-rel.src.rpm
可以用来编译生成未打包的二进制文件。
在过去的系统中,命令分别是 $rpm --rebuild 和 $rpm --recompile
一些开发者以 tar 打包的形式发布源代码,包含了一个 spec 文件。仍然可以用 RPM 来编译这个软件。在较新的系统中,命令:
$ rpmbuild -ta tarball
可以用来编译 tar 打包,生成一个 SRPM 和一个二进制的 RPM。
在过去的系统中,命令是 $rpm -ta。
要安装源代码 RPM,使用这个命令:
$ rpm -Uvh name-ver-rel.src.rpm
这个命令将原始的源代码 tar 打包,补丁还有辅助文件复制到你定义的 SOURCES 目录。spec 文件将复制到你定义的 SPECS 目录。只有当你想在创建二进制 RPM 之前,修改什么的时候,才需要这样做。
Page 11
创建新的 RPMs
准备所需的补丁和辅助文件
创建 .spec 文件
创建和测试 RPM 文件
很多时候,可以找到要编译的软件的 SRPM。但是如果还没有,那么可以用下面的简单的步骤,从头创建一个:
* 准备任何所需的补丁
* 准备任何所需的辅助文件
* 创建 .spec 文件
* 构建并测试 RPM 文件
有些时候,需要用补丁文件来修正已发布的软件。如果要为所编译的软件打补丁,就必须准备它们。
类似的,应用程序需要一些辅助文件才能运行,但是它们不随源代码发布。例如,系统守护进程经常需要一个 System V 初始化脚本,才能在系统启动时运行,但是它们很少提供这个脚本。如果需要这样的文件,必须创建它们。
另外,还必须准备指令,告诉 RPM 如何编译软件。这些指令保存在一个 spec 文件中,在编译 RPM 的时候,RPM 软件将用到它们。
在创建了这些基本的组件之后,就可以构建并测试 RPM 了。通常,这是一个交互的过程——构建过程中,补丁文件以及 spec 文件中的错误必须被捕获并更正,然后重新构建。最后,将得到可行的构建。
将你创建的,并非仅适于你自己的补丁文件,以及 spec 文件提交给软件的作者,这是不错的做法。
Page 12
为软件打补丁
SRPM 包含原始的源代码和补丁 为什么要补丁? 创建补丁
在准备要打包的软件时,通常需要修改软件的源代码。作出修改有很多原因,包括:
* 需要修改硬编码的值,例如软件中的目录路径或者使用限额
* 修正已发布的软件中的错误
* 需要将软件与系统中的其他软件更好地整合
打包者对应用程序的源代码作出的任何修改都应当以补丁文件的形式出现,而不是直接修改原始的源代码。
SRPMs 中总是包括原始的源代码,以及修改源代码所需的补丁文件。这一策略简化了长期的管理,因为它意味着所有本地的修改都保存在各个补丁文件中,可以容易地追踪。它也简化了对源代码可靠性的验证,这在今天木马横行的互联网上非常重要。
创建补丁文件很容易。要创建它,首先将要修改的文件复制一个备份,在原来的名字后面加上一个 .orig 扩展名。接下来,修改需要的地方。接下来,使用 diff 命令加上 -N, -a, -u 和 -r 选项来生成原始文件与修改过的文件的不同之处。最后,将这些不同之处保存为补丁文件。
例如,假设程序 less 需要对源代码中的 edit.c 和 filename.c 做出一些定制。要创建这些修改的补丁文件:
1. 下载并解压源代码
$ tar -zxvf less-378.tar.gz
2. 备份要修改的文件
$ cd less-378
$ cp edit.c edit.c.orig
$ cp filename.c filename.c.orig
3. 修改源代码
$ vi edit.c filename.c
4. 将修改过的不同之处保存到补丁文件中
$ diff -Naur edit.c.orig edit.c > edit.patch
$ diff -Naur filename.c.orig filename.c > filename.patch
这时,生成了两个针对 less 源代码的补丁文件,可以用来创建打过补丁的 less 的 SRPM。
Page 13
创建辅助文件
定时任务 日志轮换 环境设置 特殊情况
很多时候,需要创建辅助文件来正确地运行一个应用程序。很多应用程序需要规律性地定时运行。例如,SquirrelMail 程序创建临时文件,并由定期运行的 tmpwatch 工具删除它。在 Redhat 和 SuSE 发行版中,下列目录被用于执行定时任务:
* /etc/cron.d/
* /etc/cron.hourly/
* /etc/cron.daily/
* /etc/cron.weekly/
* /etc/cron.monthly/
应用程序可以在这些目录中插入 shell 脚本,这些脚本将被每小时,每天,每周或每月执行一次。需要更灵活的定时的程序可以将 crontab 放在 /etc/cron.d/ 目录。在打包需要定时运行某个命令的应用程序时,必须创建合适的文件,放在其中某个目录中。
类似的,一些应用程序需要 shell 或者环境的修改。打包时进行这些修改的 shell 脚本可以放在 /etc/profile.d/ 目录。
会生成日志文件的程序需要保证日志文件可以定期得到轮换,因此应当将一个进行设置的文件放在 /etc/logrotate.d/ 目录中。
需要在系统启动时运行的守护进程需要创建一个初始化脚本。大多数守护进程需要的是一个 System V 启动脚本,而采用超级进程启动的守护进程需要创建的是一个 xinetd 或是 inetd 初始化脚本。
一些程序需要更多配置。基于 X 的应用程序需要向 X 环境中的菜单系统添加条目,因此需要提供一个配置文件,向菜单结构中添加它们。Web 应用程序和 Apache 模块总是需要对 Apache web 服务器的配置进行修改,因此需要配置文件来修改 Apache web 服务器的行为。进行认证的应用程序需要为 PAM 子系统提供配置文件。
Page 14
创建 System V 初始化脚本
独立的守护进程 chkconfig
使用 System V 初始化脚本允许使用标准的方法来管理独立的守护进程,运行:
# /etc/init.d/script name (start|stop|restart)
在为守护进程创建 RPM 的时候,最好创建并安装 SysV 初始化脚本,这样系统管理员可以像管理其他系统自带的守护进程一样,管理它们。
在创建 SysV 初始化脚本的时候,可以基于已有的,简单的脚本,做出必要的修改。在 rhel/fc 中可以参考 /etc/init.d/smartd,在 SLES/SL 中提供了 /etc/init.d/skeleton。
rhel/fc 中,SysV 初始化脚本的官方文档可以在 /usr/share/doc/initscripts-*/sysvinitfiles 文件中找到,而 SLES/SL 中,可以查看 /etc/init.d/README。
chkconfig 命令允许系统管理员容易地控制守护进程应当在哪些运行级启动。例如:
# chkconfig --level 2345 httpd on
要启用这一控制,SysV 初始化脚本的开始必须有特殊的两行,例如:
#!/bin/bash
#
# startup script for the Apache Web Server
#
# chkconfig: 2345 85 15
# description: Apache is a World Wide Web server.
#
首先,chkconfig: 这一行表示,这个守护进程默认应当在运行级 2, 3, 4 还有 5 启动,启动顺序是 85,结束顺序是 15。如果在任何运行级都不应自动启动服务,那么在运行级处使用负号,不要使用数字。这种情况下,安装 RPM 之后,系统管理员可以用
# chkconfig scriptname on
来注册 SysV 初始化脚本。
在 RPM spec 文件中,在 post 安装后脚本部分,应当用这个命令来注册 SysV 初始化脚本:
/sbin/chkconfig --add scriptname
Page 15
创建菜单
freedesktop.org 桌面菜单规约 .desktop 文件
用 RPM 打包应用程序时,最好为它创建一个菜单入口,这样用户可以容易地找到并执行它。
历史上,GNOME 和 KDE 桌面使用自己不同的菜单,菜单文件有不同的格式。发现这个问题后,两个组织走到一起,创建了桌面入口标准。
标准定义了目录 /usr/share/applications/ 为每个菜单入口定义了一个 XML 文件,文件名是 applicationname.desktop
创建了 .desktop 文件之后,可以用 desktop-file-install 命令安装它。这个文件可以用 desktop-file-validate 命令来验证。
对于基本的没有提供描述译文的 .desktop 文件,可以直接在打包的 spec 文件中定义并创建它。
.desktop 文件的完整结构和规则可以在这里找到:
http://standards.freedesktop.org/menu-spec/latest/
spec 文件范例,如何生成和安装 .desktop 文件
%install
......
# 创建菜单入口
cat > %{name}.desktop <[Desktop Entry]
Name=BZFlag
Comment=%{summary}
Exec=%{name}
Icon=bzflag-m.xpm
Terminal=0
Type=Application
EOF
mkdir -p %{buildroot}%{_datadir}/applications
desktop-file-install --vendor TimRiker --dir %{buildroot}%{_datadir}/applications --add-category X-Red-Hat-Extra --add-category Application --add-category Game %{name}.desktop
Page 16
.spec 文件
定义元信息 编译 安装 脚本
创建了所需的补丁文件和辅助文件之后,必须创建一个 spec 文件。spec 文件是以一种混合了宏语言、shell 命令以及描述文本的方式书写的。在 spec 文件中,数字符号 (#) 用来表示注释,与绝大多数其他 Unix 配置文件中是一样的。
spec 文件包含几个紧密相关的段落:
* Header 头部
* Prep 准备
* Build 构建
* Install 安装
* Files 文件
* Scripts 脚本
* Changelog 变更记录
总之,这些段落定义了构成应用程序的源文件和补丁,提供了源代码以及应用程序用途的详细信息,指示 RPM 如何编译,定义了 RPM 在安装时需要安装的文件,以及如何安装它们。spec 文件也包含可选的脚本,可以分别在安装过程和卸载过程的前后执行。
Page 17
构建 RPM 过程中涉及到的目录和文件
foo.spec
Summary: The world famous foo
Name: foo
Version: 1.03
Release: 1
License: GPL
Group: Application/System
Source0: foo-%{version}.tar.bz2
Source1: foo.sysinit
Patch0: foo-fix1.patch
Patch1: foo-fix2.patch
BuildRoot: /var/tmp/%{name}-root
%description
This foo daemon serves bar clients.
%prep
%setup -q
%build
%configure
make
%install
rm -rf %{buildroot}
%makeinstall
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root)
/etc/init.d/foo
%{_sbindir}/foo
/usr/share/man/man8/foo.8
%files devel
%defattr(-,root,root)
/usr/include/foo.h
/usr/lib/foo.a
%changelog
* Mon Apr 30 2003 Dax Kelson
- ver 1.03
1. %prep
* 将文件 (SOURCES/) 解压到构建目录 (BUILD/)
* 打补丁 (SOURCES/ => BUILD/)
2. %build
* 配置 (BUILD/)
* 编译 (BUILD/)
3. %install
* 创建虚拟根文件系统 (/var/tmp/foo-root/)
* 将编译后的二进制文件和相关文件复制到虚拟根分区中的安装位置 (BUILD/ => /var/tmp/foo-root/)
4. %files
* 指定虚拟根分区中,要打包到不同的 RPMs 中的文件 (/var/tmp/foo-root/ => RPMS/i386)
Page 18
使用宏
在 RPM 中大量使用了宏,来进行配置。配置宏可以设置为全局的,只要放在 /usr/lib/rpm/macros 配置文件中。也可以进行个人设置,当 RPM 的任何命令执行时,会查找配置文件 $HOME/.rpmmacros,文件中所定义的任何配置指令将覆盖全局的配置选项。
宏也常常用在 spec 文件中。在 spec 文件中常用的命令都有预先定义的宏,很多系统中常用的目录和路径也有预先定义的宏。
在配置文件和 spec 文件中,为宏名称赋值的方法是,首先写出宏名称,接着写出值。例如,$HOME/.rpmmacros 中下面的语句
%_topdir /export/home/rpmmaker/rpmbuild
将 /export/home/rpmmake/rpmbuild 赋给宏 %_topdir。
在配置文件和 spec 文件中,宏的值可以这样引用,只要将宏名称包含在花括号中就可以了。例如,任何时候宏 %{_topdir} 出现在 spec 文件中时,对于设定了这个宏的用户,它将被自动替换为值 /export/home/rpmmaker/rpmbuild
由于宏在书写 spec 文件时如此有用,很多发行版销售商提供了很多预定义的宏,可以在书写 spec 文件时使用。在 Redhat 发行版中,这些销售商自定义的宏放在 /etc/rpm 子目录。在 SuSE 发行版中,这些销售商自定义的宏放在 /usr/lib/rpm/suse_macros 文件中。另外,/usr/lib/rpm 目录中的配置文件定义了很多标准的宏。在为多种发行版构建打包时,必须小心不要使用销售商自定义的宏。
Page 19
常用的宏
%_prefix /usr
%_exec_prefix %{_prefix}
%_bindir %{_exec_prefix}/bin
%_sbindir %{_exec_prefix}/sbin
%_libexecdir %{_exec_prefix}/libexec
%_datadir %{_prefix}/share
%_sysconfdir %{_prefix}/etc
%_sharedstatedir %{_prefix}/var
%_lib lib
%_libdir %{_exec_prefix}/%{_lib}
%_includedir %{_prefix}/include
%_oldincludedir /usr/include
%_infodir %{_prefix}/info
%_mandir %{_prefix}/man
%configure \
CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS; \
CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS; \
FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS; \
./configure --host=%{_host} --build=%{_build} \\\
--target=%{_target_platform} \\\
--program-prefix=%{?_program_prefix} \\\
--prefix=%{_prefix} \\\
--exec-prefix=%{_exec_prefix} \\\
--bindir=%{_bindir} \\\
--sbindir=%{_sbindir} \\\
--sysconfdir=%{_sysconfdir} \\\
--datadir=%{_datadir} \\\
--includedir=%{_includedir} \\\
--libdir=%{_libdir} \\\
--libexecdir=%{_libexecdir} \\\
--localstatedir=%{_localstatedir} \\\
--sharedstatedir=%{_sharedstatedir} \\\
--mandir=%{_mandir} \\\
--infodir=%{_infodir}
%makeinstall \
make \\\
prefix=%{buildroot}%{_prefix} \\\
exec_prefix=%{buildroot}%{_exec_prefix} \\\
bindir=%{buildroot}%{_bindir} \\\
sbindir=%{buildroot}%{_sbindir} \\\
sysconfdir=%{buildroot}%{_sysconfdir} \\\
datadir=%{buildroot}%{_datadir} \\\
includedir=%{buildroot}%{_includedir} \\\
libdir=%{buildroot}%{_libdir} \\\
libexecdir=%{buildroot}%{_libexecdir} \\\
localstatedir=%{buildroot}%{_localstatedir} \\\
sharedstatedir=%{buildroot}%{_sharedstatedir} \\\
mandir=%{buildroot}%{_mandir} \\\
infodir=%{buildroot}%{_infodir} \\\
install
Page 20
常用的头部字段
Name, Version, Release, License, Group, Source, Patch, URL, Requires, BuildRequires
Head 段落通常是 spec 文件的第一段。它提供了要打包的应用程序的信息。头部的字段包括:
* Name - 应用程序的名称
* Version - 应用程序的版本
* Release - 打包的修订版本
* License - 许可方式 (警告:不要用 Copying 或者 Copyright.)
* Group - 应用程序所属的组
* Source - 应用程序的源代码
* Patch - 应用程序的补丁
* URL - 应用程序原始代码的位置
* Requires - 应用程序运行所必需的软件
* BuildRequires - 编译应用程序时必需的软件
Group 字段有效的取值可以在 Redhat 发行版的 /usr/share/doc/rpm-*/GROUPS 文件中找到。
通常,一个 RPM 会需要多于一个 Source 文件和/或 Patch 文件。这时,Source 和 Patch 字段只要简单地编号:
Source0:
Source1:
Patch0:
Patch1:
Requires 和 BuildRequires 字段是可选的。RPM 会在构建时自动计算软件的依赖性关系。Requires 字段允许开发者列出运行时依赖关系,如果他们需要的话。类似的,BuildRequires 字段用来指定为正确编译,必须安装的软件。尽管不常用,指出任何不明显的构建依赖,警告试图编译软件的人,还是礼貌的做法。Requires 和 BuildRequires 都可以列出它们需要的软件名称,如果需要特定的版本,就列出名称和版本号。
头部通常还有两个字段。Summary 字段用来提供要打包的应用程序的短的,一行的自荐性描述,而 %description 字段提供很长的,可能分为多个段落的描述。
如果要在 spec 文件中创建,定义使用自定义宏,它们通常放在头部。
Page 21
高级的头部字段 Arch, Epoch
特殊情况下会在头部使用其他的字段。很多 Architecture 选项可以用来控制软件包构建的体系结构。BuildArch 用来强制软件包为特定体系结构构建,而不是为构建过程所在的平台的默认体系结构。通常,它用来指示所构建的打包是一个 .noarch.rpm:
BuildArch: noarch
并不是所有软件都能在任何平台中编译,就好像并不是所有软件都能在任何体系结构中运行一样。两个指令可以用来强制这些要求。ExclusiveArch 可以用来列出支持这一软件的平台,在其他平台中 RPM 将不会编译它。ExcludeArch 可以用来列出不支持这一软件的平台,RPM 在其他平台中才会编译它。语句
ExcludeArch: s390 s390x
表示软件应当在除了 31 位和 64 位的 s/390 硬件之外的那些机器上构建,而语句
ExclusiveArch: i386 s390 s390x x86_64
表示软件包应当只在 32 位 x86 硬件,31 位和 64 位 s/390 硬件以及 64 位 AMD (Opteron) 硬件中构建,但不在任何其他系统中构建。
RPM 在头部还提供了 Epoch 字段。通常,RPM 软件使用软件包版本和发行标记来判断一个软件包是否比另一个要新。一些软件使用非标准的版本号,或者改变了版本命名。例如,Postfix MTA 过去使用 YearMonthData 作为版本号 (类似于 postfix-19990906.tar.gz)。最近,Postfix 的作者采用了更为传统的双数位版本命名系统 (类似于 postfix-2.0.9.tar.gz)。在 RPM 比较 19990906 与 2.0.9 的时候,19990906 显然要更新 (版本号更高),尽管实际上它出现四年后,postfix-2.0.9 才发布。要更正这些问题,RPM 使用 Epoch 字段。通常,如果不出现,这个字段被认为是 0,如果需要时可以设置为一个更高的值。当比较版本号时,RPM 首先比较 Epoch,其次是 Version,最后是 Release。因此,Postfix 打包在 Epoch 为 1,Version 为 2.0.9 时,就比 Epoch 为 0,Version 为 19990906 的打包要新了。
Page 22
Prep 段落 准备工作
在 Header 头部之后,下一段落通常是 Prep。这一段落总是以标识 %prep 开始,用来准备要编译的软件。通常,这一段落将归档中的源代码解压,并应用补丁。这些可以用标准的 shell 命令完成,但是更多地使用预定义的宏。
常见的一个宏是 %setup。
这个宏解压源代码,将当前目录改为源代码解压之后产生的目录。这个宏还有一些选项可以用。例如,在解压后,%setup 宏假设产生的目录是
%{name}-%{version}
如果 tar 打包中的目录不是这样命名的,可以用 -n 选项来指定要切换到的目录。例如:
%setup -n %{name}-April2003Rel
另一个 %setup 常用的选项是 -q,它将 tar 命令的繁复输出关闭。
这里常见的另一个宏是 %patch。
这个宏将头部定义的补丁应用于源代码。如果定义了多个补丁,它可以用一个数字的参数来指示应用哪个补丁文件。它也接受 -b extension 参数,指示 RPM 在打补丁之前,将文件备份为扩展名是 extension 的文件。
下面的宏
%patch2 -b .test
指示 RPM 应用 Patch2,将任何要修改的文件备份为扩展名是 .test 的文件。
%patch 宏的 -p 选项控制着要传给 /usr/bin/patch 命令的 -p 选项。通常,会使用 -p1,但是,这当然依赖于补丁文件是如何创建的。
Page 23
构建
在 Prep 段落之后,spec 文件通常包含一个 Build 段落,总是以 %build 标识开始。
在这个段落中,包含用来配置和编译已配置的软件的命令。与 Prep 段落一样,这些命令可以是 shell 命令,也可以是宏。
如果要编译的宏使用了 autoconf,那么应当用 %configure 宏来配置软件。这个宏自动为 autoconf 指定了安装软件的正确选项,编译优化的软件。
如果软件不是用 autoconf 配置的,那么使用合适的 shell 命令来配置它。
软件配置之后,必须编译它。由于各个应用程序的编译方法都各自不同,没有用来编译的宏。只要写出要用来编译的 shell 命令就可以了。
环境变量 $RPM_OPT_FLAGS 在编译软件时很常用。这个 shell 变量包含针对 gcc 编译器套件的正确的优化选项,使用这样的语法:
make CC="gcc $RPM_OPT_FLAGS"
或者
make CFLAGS="$RPM_OPT_FLAGS"
就可以保证总是使用合适的优化选项。也可以使用其他编译器标志和选项。默认的 $RPM_OPT_FLAGS 是:
-O2 -g -march=i386 -mcpu=i686
Page 24
Install 段落
在 Build 段落之后,是 Install 段落。这个段落总是以标记 %install 开始。
这个段落用于将已编译的软件安装到虚拟的目录结构中,从而可以打包成一个 RPM。
在 Header 段落,可以定义 Buildroot,它定义了虚拟目录树的位置,软件将安装到那里。通常,它是这样的:
Buildroot: %{_tmppath}/%{name}-root
或是
Buildroot: %{_tmppath}/%{name}-%{version}-root
使用 RPM 内建的宏来指定 /var/tmp 目录中一个私用的目录。
在 spec 文件的其余部分可以用 shell 变量 $RPM_BUILD_ROOT 获取 Buildroot 的值。
mkdir -p $RPM_BUILD_ROOT/usr/share/icons/
cp %{SOURCE3} $RPM_BUILD_ROOT/usr/share/icons/
Install 段落通常列出要将已编译的软件安装到 Buildroot 中的命令
宏 %makeinstall 可以用于安装支持 autoconf 的软件。这个软件自动地将软件安装到 $RPM_BUILD_ROOT 下的正确的子目录中。
有时,软件包必须被构建多次,由于打包错误或其他原因。每次构建时,Install 段落将复制文件到 Buildroot 中。要防止由于 Buildroot 中的旧文件而导致错误的打包,必须在安装新文件之前将 Buildroot 中任何现有的文件删除。为此,可以使用一个 clean 脚本。这个脚本通常以 %clean 标记表示,通常仅仅包含这样一句:
rm -rf $RPM_BUILD_ROOT
如果有的话,在制作了在 Install 段落中安装的文件的打包之后,将运行 %clean,保证下次构建之前 Buildroot 被清空。
Page 25
Files 段落
在 Install 段落之后,下一个段落是 Files,列出了要打包到一个 RPM 中的文件和目录。这个段落通常以标记 %files 开始。在这个段落中,每行一个,简单地列出文件和目录,相对于 Bduilroot,它们将被存档到打包中。可以在这里使用通配符,例如
/usr/bin/*
指示 RPM 将 $RPM_BUILD_ROOT/usr/bin 目录中所有文件打包。
在列出文件和目录时,必须小心列出所有需要的文件,不要列出任何不应被打包的文件。在列出一个目录时要更加小心。列出一个目录意味着 RPM 要打包这个目录以及其中的所有文件,因此语句
/usr/bin
指示 RPM 将 $RPM_BUILD_ROOT/usr/bin 目录中所有文件打包,但是也会创建一个似乎拥有 /usr/bin 目录的不正确的打包。
在 Files 段落,有一些宏可以用。应当总是应用 %defattr 宏来指定之后列出文件的默认的所有者和权限。例如,语句 %defattr(0770,root,root) 将定义其后列出的所有文件和目录,直到下一个 %defattr 为止,它们在安装后的所有者是 root.root,拥有权限 0770。另外,单独的文件可以用 %attr 指定与 %defattr 不同的所有者和权限。例如:
%files
%defattr(-,root,root)
%{_libdir}/libamanda*.so
%attr(660,amanda,disk) /var/lib/amanda/.amandahosts
一些宏用来指示要安装的文件具有特殊的属性。宏 %dir 可以用来指示要打包的是一个目录,而不是目录中的文件。宏
%config(noreplace)
用来指示被安装的是一个配置文件,在软件包升级时不应被覆盖。
Page 26
可选的脚本段落
有时需要在安装的前后,在系统中运行一些命令。例如,在安装了新的动态链接库之后,应当运行 ldconfig 命令来使系统使用新安装的库。
RPM spec 文件可以包含分别在安装和卸载前后运行的脚本。这些脚本通常在 Files 段落之后列出,是简单的 Bourne shell 脚本,列在一个指示它们何时执行的宏后面。可用的值为:
* %pre - 安装前执行
* %post - 安装后执行
* %preun - 卸载前执行
* %postun - 卸载后执行
最常见的,这些命令用在需要使用新系统帐号才能运行的软件打包中。%pre 脚本可以用来添加需要的帐号,%postun 可以用来在卸载软件时删除这个不再需要的帐号。在 Redhat 系统中准备需要用户帐号的打包时,参考 /usr/share/doc/setup-*/uidgid 文件,它列出了 Redhat 附带的软件已经使用了的 UIDs 和 GIDs。
有时,需要在 %pre, %post, %preun 和 %postun 中执行的脚本是随机的,要根据当前系统中软件的安装情况进行抉择。例如,Mailman 邮件列表管理程序需要一些邮件别名才能工作,因此它的打包需要在 %post 脚本中,向系统添加一些邮件别名,在 %postun 脚本中移除它们。这些别名要写入的位置是随系统中安装的 MTA 而不同的——postfix 使用文件 /etc/postfix/aliases 作为别名数据库,而 Sendmail 使用文件 /etc/aliases 作为别名数据库。
这种情况下,要采用的动作取决于当前系统状态的话,可以用 shell 脚本的条件判断。不过,RPM 提供了一种触发机制,可以用来在其他软件安装/卸载时执行动作。这些脚本以
%triggerin -- package
还有
%triggerun -- package
标记。第一个标记表示软件 package 安装或升级时运行的脚本,而第二个表示软件 package 卸载时运行的脚本。
Page 27
Changelog 段落
spec 中的最终段落是 Changelog 段落。这个段落总是以 %changelog 标记开始,用来列出对打包的任何修改。
尽管日志的结构技术上可以是自由格式,但是大多数 RPM 系统中使用下面的格式:
* 日期 打包人 <打包人的电子邮件> 版本-发行标记
- 所作的更改
- 其他更改
日期必须是下列格式:
Wed Nov 20 2002
这种格式的当前日期可以用命令
date +"%a %b %d %Y"
得到。
每次准备打包的新的修订版时,打包人只要在 Chanlog 段落起始处加上类似的一段。
下列范例是来自 Fedora Core 3 firefox RPM spec:
* Wed Mar 02 2005 Christopher Aillon 0:1.0.1-1.3.2
- Remerge firefox-1.0-pango-selection.patch
* Thu Feb 24 2005 Christopher Aillon 0:1.0.1-1.3.1
- Update to 1.0.1 fixing several security flaws.
- Mark some generated files as ghost (#136015)
- Add RPM version to the useragent
- BuildRequires pango-devel
- Enable pango rendering by default
- Enable smooth scrolling by default
Redhat 使用的一个约定是引用它们的错误跟踪系统的错误 Id。在这个例子中,引用了一个有关 RPM 打包的错误。详情可以通过下面的网址查看:
https://bugzilla.redhat.com/bugzilla....cgi?id=136015
Page 28-31
最后的 spec 文件
Page 32
其他内容
除了基本的 spec 文件结构,还有一些高级的需求。通常,一个应用程序需要打包为两个或多个软件包。例如,LessTif 软件包提供了多种不同的内容:一个运行时库,为连接到 Motif 部件集的软件所用,编程的头文件和库文件,开发者用它们来创建应用程序,还有一个窗口管理器。这是三个明显不同的应用程序,不同的用户需要不同的组合。因此, RPM spec 文件可以设定为生成子打包,通过同一个源代码生成两个或多个二进制打包。
另一个常见的需求是在不能获得源代码时,打包二进制文件。例如,Adobe 发布了 Acrobat Reader for Linux,但是在第七版之前,他们只发布二进制可执行文件的 tar 打包。可以为此创建 RPM,允许用户使用 RPM 工具来管理这个程序。要创建这样的 spec 文件,只要简单地省略 Build 段落,在 %install 段落中,手动复制文件到虚拟根文件系统中就可以了。
打包人有时想创建交互式的 RPM,也就是说,在安装过程中询问用户问题。RPM 故意地不支持创建交互的打包!只为保证所有安装过程可以脚本化。要小心设计软件包,避免安装时的交互。
打包人通常需要为多个发行版准备打包。需要考虑一些潜在的复杂情况,才能使单个 spec 文件用于在多个发行版中编译 RPM:
* 不同的发行版预定义了不同的宏。大多数在 Redhat 发行版中定义的宏处于一个 “基线” 上,可以假设绝大多数发行版中也定义了它们,包括 SuSE 发行版。因此,只使用 Redhat 系统中定义的宏,有助于跨发行版的兼容性。
* 不同的发行版使用不同版本的 RPM。旧版本的 Linux 发行版使用旧版本的 RPM 3,而较新的系统使用新的 RPM 4。不同的 RPM 版本中有行为和语法的差别,必须消除。
* 有时不同的发行版将文件安装在不同的位置。Linux Standards Base (LSB) 的努力消除了很多这样的因素,但是还是可能出现。
打包者总会想发布支持多种语言的打包,使用户可以看到以母语显示的打包描述以及相关信息。RPM 提供了一个 specspo 机制,可以用来为打包文件保存已翻译的消息。
Page 33
构建软件包
当准备好 spec 文件之后,接下来是使用 spec 文件构建软件。基本的构建命令,在较新的系统中是 rpmbuild -b spec,在过去的系统中是 rpm -b spec。这个命令支持下面各种不同的参数,取决于要处理 spec 文件的哪一部分:
* -bp - 处理 spec 文件的 Prep 部分
* -bc - 处理 spec 文件的 Prep 和 Build 部分
* -bi - 处理 spec 文件的 Prep, Build 和 Install 部分
* -bl - 校验 spec 文件的 Files 部分
* -bb - 根据 spec 文件构建二进制 RPM
* -bs - 根据 spec 文件构建源代码 RPM
* -ba - 根据 spec 文件同时构建二进制 RPM 和源代码 RPM
最常用的是
rpmbuild -ba spec
有时会用 --target 参数来强制 RPM 为特定的平台编译软件。例如,在 32 位 x86 系统,运行 rhel/fc 的平台中,RPM 默认生成运行在任何 32 位 x86 计算机上的打包,但是对于 80686 级别的计算机会做优化。这个选项可以用来强制 RPM 生成只在 80686 级别的计算机中运行的,或是为 AMD Athlon 更好优化过的,或是为 80386 级别的计算机优化过的打包。命令
rpmbuild -ba --target i686-redhat-linux spec
根据 spec 构建 RPM,只与 80686 级别的机器兼容,比默认的 RPM 优化要稍微更好一点。
在构建打包时,RPM 提供在命令行覆盖或修改 RPM 宏的能力。打包人通常用这个特性来生成可以用来编译相同的软件,但是使用不同选项的 spec。例如,rhel/fc 的 Postfix spec 在 Header 段落包含了各种宏定义,在编译期启用或禁用支持各种特性。这个语句
%define LDAP 0
用来定义 LDAP 的值为 0,在后面 Build 段落中的命令使用这个变量来编译不带 LDAP 支持的 Postfix。使用这样的命令行来覆盖这个变量的值:
rpmbuild -ba --define ‘LDAP 1‘ postfix.spec
Postfix 在编译时就有了 LDAP 支持。
Page 34
数字签名的软件包
由 spec 文件创建了二进制和源代码 RPM 之后,可以使用 GPG 或 PGP 为结果 RPM 签名。签名为下载软件包的最终用户提供了两个重要的功能:
* 它们证明软件包可信,向用户保证,打包来自它应该来自的地方。
* 它们保证打包的完整性,向用户保证软件包在打包人签名之后,没有遭到修改 (尽管 RPM 还通过其他机制提供了这一保证)
这些特性在当今木马横行的互联网上都非常重要。
要签署一个打包,必须首先有一个 GPG 密钥。如果没有的话,可以很容易地生成一个:
$ gpg --gen-key
生成密钥之后,修改你的 RPM macros 来指示 RPM 使用 GPG 签署打包:
echo "%_signature gpg" >> $HOME/.rpmmacros
同时,指定 RPM 应当使用哪个密钥来签署打包:
echo "%_gpg_name 邮件地址" >> $HOME/.rpmmacros
最后,指定 RPM 如何定位你的 GPG 密钥:
echo "%_gpg_path $HOME/.gnupg" >> $HOME/.rpmmacros
配置好 RPM 使用 GPG 之后,可以用 rpmsign 命令来签署你构建的打包:
$ rpmsign --addsign /path/to/the.rpm
可以导出你的公钥:
$ gpg --export --armor > gpg-pub-key
然后将公钥发给安装你的 RPM 的用户,他们可以用它来校验你的 RPM 是由你签署的。要做到这一点,他们必须首先导入你的 GPG 公钥到他们的 RPM GPG 钥匙环中:
# rpmsign --import /path/to/gpg-pub-key
导入公钥之后,可以校验打包的签名了:
$ rpmsign -K package-1.0-1.i386.rpm
package-1.0-1.i386: (sha1) dsa sha1 md5 gpg OK
如果打包通过校验,那么用户就知道它的签名来自他们信任的一方了。
Page 35
修订打包
除创建新的 RPM 之外,打包人另一个经常性的任务是更新现有的打包,在应用程序有新的版本可用时重建打包。修正现有的源代码 RPM 只要很简单的几步:
1. 安装最新的 SRPM
2. 将应用程序的最新的源代码放在 SOURCES 目录
3. 修改 spec 文件为使用最新的源代码
4. 试着做 spec 文件的 Prep 段落:
$ rpmbuild -bp application.spec
在尝试的时候可能会发现,一些补丁不再适用于新版本的源代码了。这时,查看补丁文件的内容,以及应用程序的源代码,检查为什么不适用。
1. 补丁无法应用,是因为不再需要了。这时,只要从 spec 文件中移除补丁就可以了
2. 补丁仍然需要,但是无法应用,因为应用程序的代码在其他部分发生了变化。这时,创建一个新版本的补丁,使它可以适用于新版本的源代码
可以成功完成 Prep 段落之后,更新 spec 文件中的 Changelog 段落以及版本信息,然后构建新打包:
$ rpmbuild -ba application.spec
Page 36
其他资源
有很多资源,提供了更多有关 RPM 和如何创建 RPM 的信息。最好的资源是 http://www.rpm.org ,提供了各种有关 RPM 的文档,以及 RPM 的源代码。这个站点有一本免费下载的书,《Maximum RPM》。尽管它有些过时,但是仍然是不错的补充资源。
很多工具可以简化 RPM 的创建,包括文本编辑器的 spec 文件编辑模式:
http://www.tihlde.hist.no/~stigb/rpm-spec-mode.el
http://pegasus.rutgers.edu/~elflord/vim/syntax/spec.vim
还有各种生成 spec 文件的工具:
http://rpmrebuild.sourceforge.net
http://www.cpan.org/modules/by-modul...le-1.17.tar.gz
http://checkinstall.izto.org
为多个系统准备打包的主要困难是需要有为每个系统准备独立的构建环境。有很多程序可以用来简化在同一台机器上创建多个构建环境:
http://thomas.apesstaart.org/projects/mach
http://www.solucorp.qc.ca/miscprj/s_context.jc
一些网站提供各种高质量的编译好的 RPM,也可以用来寻找已有的 RPM:
http://freshrpms.net
http://www.fedoraproject.org
http://www.rpmfind.net
http://www.GuruLabs.com/downloads.html
有很多工具可以用来简化安装 RPM 的工作,包括:
http://current.tigris.org
http://www.linux.duke.edu/projects/yum
http://www.autorpm.org
http://www.mat.univie.ac.at/~gerald/autoupdate
http://apt4rpm.sourceforge.net
http://www.smartpm.org
实验
任务 1 (6 小题) (p.39-p.42)
任务 2 (10 小题) (p.43-p.51)
任务 3 (53 小题) (p.52-p.79)
任务 4 (13 小题) (p.80-p.86) RPM Builder 能够将tar.gz 格式的文件转换为RPM 格式的包。它可以自动的产生所必需的RPM 格式文件摸板,然后创建RPM 格式文件和SRPM 格式文件。即使你不了解RPM 包,你也可以使用这个软件创建一个RPM 包。
http://download.enet.com.cn/html/262392001011002.html
rpmbuilder 的下载地址
Clear River Technologies
http://www.klabs.net/rpmbuilder/
Page 0
Guru Labs
《Creating RPMs (Student version)》v1.0 (创建 RPM 打包,学生版)
本文目的 1. 作为我们的教学课件的范例用于评估 2. 为系统管理员提供高质量的 RPM 手册
有关本教程 您看到的蓝色背景,模拟了印刷 Guru Labs 课件所用的自定义纸张。学生版不包括教师版中的指令备注和教学提示。
有关我们特别的排版信息,参见 http://www.gurulabs.com/courseware/c...are_layout.php
有关我们提供的免费教学内容,包括本文的最新版,参见 http://www.gurulabs.com/goodies/
范例在以下平台中得到验证 rhel4, fc3, suse9, suse9.2
关于 Guru Labs
Guru Labs 是一个 Linux 培训公司,由 Linux 专家创建于 1999,提供最好的 Linux 培训和课件。全面的内容请参见 http://www.gurulabs.com
Copyright Guru Labs, L.C. 2005
Licensed under the Creative Commons Attribution-NonCommercial-NoDerivs License. http://creativecommons.org/licenses/by-nc-nd/2.0 (译文违反了许可,但是我想这份许可的 -nd- 是由于采用了特殊的背景和排版,而不是因为翻译能涉及到的那些 (应当) 人所共知的知识?)
Guru Labs 801 N 500 W Ste 202 Bountiful, UT 84010 Ph: 801-298-5227
WWW.GURULABS.COM
Page 1
目标
* 理解 UNIX/Linux 软件管理的历史概况
* 描述 RPM 系统的特点与结构
* RPM 的日常应用,各种不同的 RPM 打包的处理
* 修改并重构建已有的 SRPMS
* 学习 RPM SPEC 文件的语法,以及编译基础要求
* 创建新的 SPEC 文件,辅助文件以及 RPM 文件
* 高级的 RPM 创建技术
* 处理 Redhat 与 SuSE 发行版中,RPM 系统的不同之处
Page 2
处理打包
Unix 打包 (System V packages)
Linux 打包 (Slackware Tarballs, RPMs, Debian DPKGs)
传统上,UNIX 系统的软件都是以源代码形式发布的。要使用某个软件,管理员必须为要运行它的系统适当地编译它,然后安装它。如果它要求任何辅助的软件包, 那么也必须同时安装。如果要求本地进行任何定制,那么就必须去配置。
如果软件需要升级,管理员必须找到系统中, 属于这个软件的所有文件,替换为升级的版本,小心地保留那些本地作出的配置修改。
现在,考虑一个典型的 UNIX 工作站应用程序,例如 Mozilla。基本的 Mozilla 应用程序包含大约 495 个文件,分布在大约 10 个不同的目录中。在删除时,管理员必须找到所有这些文件并且删除。在升级时,管理员必须手工地替换所有文件。在运行时,Mozilla 要求安装大约 50 种其他可执行文件和运行时库 (而这些又会依赖于其他库文件)。
手工管理所有这些不是不可能的, 并且 Unix 管理员已经这样做了三十多年了,不过,很多服务提供商开发了简化此类工作的工具。在商业 Unix 世界中,System V Unix 定义了一种标准“打包”系统,这成为了此类软件的基础,包括 Solaris 中使用的 pkg 格式,还有 HP-UX 中使用的 depot 格式。这些软件包系统提供了各种工具,可以用来安装、卸载和升级打包中的软件。打包中包含了软件和元数据 (例如列举出为了使软件可以运作,必须安装的其他软件等等)。
在 Linux 世界中,最初的软件没有打包,与 Unix 世界中完全相同。后来,在 1993 年 Slackware 发行版出现时,它引进了一种很初级的打包格式。之后,两种新的发行版,Redhat 与 Debian,都开始为 Linux 开发更多功能的打包软件。Debian 引进了 DPKG 打包系统,而 Redhat 引进了 RPM 打包系统。从那时开始, RPM 打包系统成为了 Linux 社区中的事实标准。它为几乎所有著名商业 Linux 发行版所用,包括来自 Redhat, SuSE 和 Mandrake 的那些。RPM 也是 Linux 世界中软件包管理的法律标准, Linux 标准化组织 LSB (Linux Standards Base) 要求相容于 LSB 的系统支持 RPM 文件的安装。
Page 3
RPM 特性
非交互安装,可运行脚本,可追踪/校验/查询已安装的文件,可追踪依赖性关系,可追踪整个源代码和编译过程,数字签名
RPM, RPM 包管理工具,提供了各种特性,使之成为 Linux 社区中杰出的包管理工具,大大简化了 Linux 管理员的工作。
RPM 提供了一系列的工具,可以用来实现非交互地,可运行脚本的安装过程。当软件安装之后,RPM 提供的工具可以用来追踪已安装的文件,使得卸载和升级非常简单,管理员可以检查软件安装是否正确,已安装的文件是否被修改过。另外,RPM 提供了一系列工具,可以用来查找已安装的文件,判断哪些程序在使用它们。
RPM 有杰出的依赖性追踪能力,意味着在安装新软件包时,它可以保证为了运行新软件,所有必需的软件都已经安装。在卸载软件时,它可以首先检测操作是否会影响其他应用程序。
另外,RPM 提供了一系列工具,管理从打补丁、配置直到编译的整个过程。当编译一个软件时,RPM 可以从原始的源代码开始,生成所需的补丁,将打补丁,配置源代码和编译源代码以产生可执行文件的过程脚本化。RPM 的这种功能极大地简化了企业中自定义软件的维护过程。
最后,RPM 允许将所有已打包的软件签名,使用公钥技术。这种特性允许验证 RPM 的可靠性,防止安装木马程序。
Page 4
RPM 结构
RPM 打包文件,数据库 /var/lib/rpm,工具 rpm,rpmbuild,rpmsign,rpm2cpio,RPM 配置文件 宏
RPM 系统包含多个组件。要使用 RPM 安装的软件必须打包成特定的格式,RPM 打包文件。RPM 打包文件是一个存档文件,包含了要安装的文件,以及元数据。RPM 系统使用元数据来保证将文件以正确的权限和所有者,安装到正确的位置。
在使用 RPM 安装软件时,软件名称和其他一些属性被记录到 RPM 数据库中,通常数据库在 /var/lib/rpm 目录。数据库包含了已安装程序的列表,以及属于这些软件的文件,使得以后可以方便地卸载或升级软件。它也记载了文件的属性,包括文件的大小,时间戳,校验和——保证可以在以后检测文件的正确性。数据库也包含了每个程序的依赖性信息,保证管理员安装软件时,所需的软件都已安装,卸载软件时,不会破坏其他现有的程序。
RPM 还包括一些工具。大多数 RPM 管理任务中,最基本的工具是 /bin/rpm 命令。在年代久远的系统中,如果用的是旧版本的 RPM,那么就只有这一个命令。在稍微新一些的系统中,新版本的 RPM 将过去 /bin/rpm 的许多功能移动到了辅助工具中。例如,/usr/bin/rpmbuild 命令用来生成新的 RPM 打包文件,/usr/bin/rpmsign 命令用来签署打包。
/usr/bin/rpm2cpio 命令一直都有,用来将一个 RPM 打包文件转换成标准的归档文件格式。
RPM 还有很多配置文件。在 rhel/fc 中,这些文件在 /etc/rpm 和 /usr/lib/rpm 目录,在 SuSE 中,这些文件只在 /usr/lib/rpm 目录。这些配置文件主要定义了宏——运行 RPM 命令或解析 RPM 打包文件时使用的快捷命令。
Page 5
RPM 打包文件
命名约定 体系结构 格式
要使用 RPM 安装的软件必须打包成 RPM 格式的文件。文件名应当有以下的格式:
名称-版本-发行标记.体系结构.rpm
在这个文件名中,名称表示包含在文件中的软件名,通常是软件的名字。版本表示软件的版本。尽管 RPM 文件格式以及工具没有强制要求,还是应当使用数字来表示版本。在这里使用字母会给很多 RPM 的前端带来问题。
发行标记用来表示对某个版本的打包的修正。有时,在为某个应用程序的某个版本制作 RPM 时会出错。这时,可以制作相同版本的修正了错误的新的 RPM。发行标记用来追踪打包文件的修正。这里也应该是一个数字,并且每次打包被修正后都应递增。
体系结构是这个 RPM 可以安装的系统平台。典型的值可以是:
* i386 任何 32 位 x86 系列 CPU
* i686 任何 686 级别的 32 位 x86 系列 CPU
* ppc64 64 位 PowerPC CPU
* x86_64 AMD 或 Intel 64 位 CPU
* ia64 64 位安腾 CPU
* sparc64 64 位 UltraSparc CPU
除了二进制可执行文件,RPM 还可以用来打包独立于平台的可执行程序 (例如使用解释性语言编写的程序,如 Lips, Perl 或 Java)。如果 RPM 包含的代码可以在任何 CPU 中运行,或者包含文档等独立于平台的文件,那么体系结构通常是 noarch
RPM 打包文件也可以用来打包应用程序源代码,补丁和用来指示如何配置和编译源代码的脚本。这些打包文件的体系结构使用 src,表示它们包含源代码而不是可执行文件。
如果 RPM 用作打包应用程序源代码,但是事实上不包括源代码的原始文件,只在元数据中保留了对源代码的引用,那么体系结构应当使用 nosrc,表示它们实际上没有打包源代码,但是可以像 src.rpm 一样使用。
不考虑它们的名字差别,所有 RPM 打包文件都是一个 cpio 归档文件,附加一个二进制的头部。
Page 6
使用 RPM
安装 升级 删除 查询/校验软件包/文件 rpm -iUFeqV
RPM 打包文件在安装时通常使用 rpm 命令和 -U 参数。通常,还要加上 -v 选项,使得 rpm 输出更多信息,还会加上 -h 选项,使得 rpm 执行时显示进度条
如果想安装一个软件包,同时还保留旧版本 (只有当两个版本中没有相同的文件时才可能做到),那么使用 -i 参数。通常在安装内核时会这样做,为了防止新内核出错,将旧内核保留下来。
也可以用 -F 参数来升级软件包 (通常,还要加上 -v 和 -h 选项),这个参数使得已安装的旧软件包得到更新,但是如果没有安装过,那么就不会安装它。
在进行升级或更新时,rpm 工具比较要安装的 RPM 版本与系统 RPM 数据库中,已安装的版本。如果要安装的软件包版本比已安装的版本更新,那么就升级。如果相反,那么 RPM 拒绝降级。如果版本号相同,RPM 就比较发行标记,只有当新打包的发行标记比已安装的打包的发行标记要新, 才进行升级。
软件包安装之后,可以用 -e 参数来删除
在删除软件包的时候,只要给出软件包的名称。在安装新软件包或者升级时,必须指定打包的全名。
打包文件和已安装的打包都可以查询。rpmquery 命令,或者 rpm 命令加上 -q 参数,都可以做很多查询。类似的,已安装的软件可以用 rpmverify 命令,或者 rpm 命令加上 -V 参数来校验。
Page 7
源代码 RPM 文件
原始源文件 补丁 辅助文件 脚本 .spec
rpm 命令可以用来处理源代码 RPM 文件 (SRPMs)。SRPMs 打包是用来构建作为最终产品安装到系统中的二进制 RPMs 打包的,如 .i386.rpm 和 .noarch.rpm 等等。SRPMs 包含几种不同的文件:
* 程序的最初的源文件
* 任何修改源程序的补丁
* 任何辅助的文件,例如 System V 启动脚本
* 指明如何配置和编译源代码的脚本。脚本通常命名为 name.spec,其中 name 是软件名
RPM 背后的一条设计原则是,软件包应当总是从最初的源代码编译。这一规则对于 Linux 社区很重要,每个程序都是由互联网上的松散的组织开发出来的,然后被 Redhat 和 SuSE 这样的发行版销售商整理到一起,成为一个集成的操作系统。发行版销售商经常需要修改源代码,使之可以更好地集成到发行版中,同样,最终用户也经常需要重新编译,有时需要打补丁,使得销售商提供的应用程序可以更好地适应自己的环境。从最初的源代码开始制作 RPM,加上各自的补丁,有助于简化长期的管理。这也使得最终用户可以容易地发现软件包作出了哪些修改。
通常,支持创建 RPM 的应用程序开发者会发布 SRPMs。不过有些开发者会仅仅发布标准的 Unix tar 打包格式的源代码,在其中包含一个 .spec 文件,指明如何从源代码编译生成一个二进制 RPM。
Page 8
使用源代码 RPMs
重新构建 创建
尽管管理员总是可以找到他们要安装的软件的二进制 RPMs,一些时候他们还是需要编译。有很多从源代码编译的理由:
* 发行版中未包含此软件
* 需要更新软件版本
* 需要以与发行版中的版本不同的选项和特性来编译应用程序
* 需要修正发行版中的版本包含的错误
在从源代码编译时,管理员仍然希望从 RPM 之类的包管理系统中得到便利,包括可以将来轻松地卸载,还有需要的时候升级等等。类似的,管理员在使用 RPM 工具编译时也会得到好处,包括内在的对构建命令的追踪,以及对补丁的取舍。
由于这些原因,管理员会选择从 SRPM 编译生成 RPMs。要生成二进制 RPM,管理员首先需要源代码 RPM,包含了用于生成二进制 RPM 的源代码。管理员通常有两种办法来获得 SRPM:
* 从头创建一个 SRPM
* 使用现有的 SRPM
当使用现有的 SRPM 时,管理员可以原样使用它,也可以进行定制。所有的操作都可以用 RPM 工具完成。
Page 9
准备构建
安装必需的软件 准备非 root 的构建环境
在从 SRPMs 构建 RPMs 的时候,首先需要进行准备工作。编译时需要的软件必须安装在用于构建的机器上。通常,这一需求意味着一般的开发工具,例如 gcc C 编译器以及 make 命令必须安装。与 Linux 发行版的安装方式相关,这些工具可能已经安装了,也可能没有。除了开发工具之外,很多软件包含编译期依赖关系,在编译时必须满足。很多应用程序要求在编译时必须能找到支持库和头文件,如果没有的话必须也安装它们。
二进制文件,一旦被编译,那么就可以在与它被编译的系统中,拥有相同的库文件的系统中顺利执行。因此,最好在与安装的目标系统相同的操作系统中编译它。
在从 SRPMs 构建 RPMs 的时候,尽可能使用非 root 用户,这非常重要。作为 RPM 构建过程的一步,RPM 工具将编译好的软件安装到一个虚拟的文件系统环境中。如果控制 RPM 构建过程的 spec 文件出错,可能导致 RPM 安装到真实的文件系统中。使用非 root 用户构建 RPM,尽管不是总是可行,但是防止了偶然的写入真实文件系统的事故,因为非 root 用户通常对 RPM 在安装时试图写入的目录没有写权限。
在当前的 SuSE 发行版中,RPMs 被配置为支持非 root 用户在 /usr/src/packages 子目录构建 RPM。在 Redhat 发行版中,必须进行配置,才能支持非 root 用户的构建。
要在 Redhat 发行版中配置普通用户构建 RPM:
1. 作为要执行构建的非特权用户登录
2. 创建 RPM 构建所需的目录结构
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,S{OURCE,PEC,RPM}S}
或者
$ cp -a /usr/src/redhat ~/rpmbuild
3. 配置 RPM 在构建时使用新的目录结构,而不是默认的目录结构:
$ echo "%_topdir $HOME/rpmbuild" > ~/.rpmmacros
在执行了这些命令之后,RPM 将会在用户的个人目录下 rpmbuild 目录中构建。要在其他位置构建 RPMs,只要调整路径为合适的值。
Page 10
重构建现有的打包
源代码 RPMs
包含 .spec 文件的 tar 打包
准备好合适的编译环境之后,就可以重建现有的打包了。在较新的系统中,命令:
$ rpmbuild --rebuild name-ver-rel.src.rpm
可以用来编译 SRPMs 生成二进制 RPM,而命令
$ rpmbuild --recompile name-ver-rel.src.rpm
可以用来编译生成未打包的二进制文件。
在过去的系统中,命令分别是 $rpm --rebuild 和 $rpm --recompile
一些开发者以 tar 打包的形式发布源代码,包含了一个 spec 文件。仍然可以用 RPM 来编译这个软件。在较新的系统中,命令:
$ rpmbuild -ta tarball
可以用来编译 tar 打包,生成一个 SRPM 和一个二进制的 RPM。
在过去的系统中,命令是 $rpm -ta。
要安装源代码 RPM,使用这个命令:
$ rpm -Uvh name-ver-rel.src.rpm
这个命令将原始的源代码 tar 打包,补丁还有辅助文件复制到你定义的 SOURCES 目录。spec 文件将复制到你定义的 SPECS 目录。只有当你想在创建二进制 RPM 之前,修改什么的时候,才需要这样做。
Page 11
创建新的 RPMs
准备所需的补丁和辅助文件
创建 .spec 文件
创建和测试 RPM 文件
很多时候,可以找到要编译的软件的 SRPM。但是如果还没有,那么可以用下面的简单的步骤,从头创建一个:
* 准备任何所需的补丁
* 准备任何所需的辅助文件
* 创建 .spec 文件
* 构建并测试 RPM 文件
有些时候,需要用补丁文件来修正已发布的软件。如果要为所编译的软件打补丁,就必须准备它们。
类似的,应用程序需要一些辅助文件才能运行,但是它们不随源代码发布。例如,系统守护进程经常需要一个 System V 初始化脚本,才能在系统启动时运行,但是它们很少提供这个脚本。如果需要这样的文件,必须创建它们。
另外,还必须准备指令,告诉 RPM 如何编译软件。这些指令保存在一个 spec 文件中,在编译 RPM 的时候,RPM 软件将用到它们。
在创建了这些基本的组件之后,就可以构建并测试 RPM 了。通常,这是一个交互的过程——构建过程中,补丁文件以及 spec 文件中的错误必须被捕获并更正,然后重新构建。最后,将得到可行的构建。
将你创建的,并非仅适于你自己的补丁文件,以及 spec 文件提交给软件的作者,这是不错的做法。
Page 12
为软件打补丁
SRPM 包含原始的源代码和补丁 为什么要补丁? 创建补丁
在准备要打包的软件时,通常需要修改软件的源代码。作出修改有很多原因,包括:
* 需要修改硬编码的值,例如软件中的目录路径或者使用限额
* 修正已发布的软件中的错误
* 需要将软件与系统中的其他软件更好地整合
打包者对应用程序的源代码作出的任何修改都应当以补丁文件的形式出现,而不是直接修改原始的源代码。
SRPMs 中总是包括原始的源代码,以及修改源代码所需的补丁文件。这一策略简化了长期的管理,因为它意味着所有本地的修改都保存在各个补丁文件中,可以容易地追踪。它也简化了对源代码可靠性的验证,这在今天木马横行的互联网上非常重要。
创建补丁文件很容易。要创建它,首先将要修改的文件复制一个备份,在原来的名字后面加上一个 .orig 扩展名。接下来,修改需要的地方。接下来,使用 diff 命令加上 -N, -a, -u 和 -r 选项来生成原始文件与修改过的文件的不同之处。最后,将这些不同之处保存为补丁文件。
例如,假设程序 less 需要对源代码中的 edit.c 和 filename.c 做出一些定制。要创建这些修改的补丁文件:
1. 下载并解压源代码
$ tar -zxvf less-378.tar.gz
2. 备份要修改的文件
$ cd less-378
$ cp edit.c edit.c.orig
$ cp filename.c filename.c.orig
3. 修改源代码
$ vi edit.c filename.c
4. 将修改过的不同之处保存到补丁文件中
$ diff -Naur edit.c.orig edit.c > edit.patch
$ diff -Naur filename.c.orig filename.c > filename.patch
这时,生成了两个针对 less 源代码的补丁文件,可以用来创建打过补丁的 less 的 SRPM。
Page 13
创建辅助文件
定时任务 日志轮换 环境设置 特殊情况
很多时候,需要创建辅助文件来正确地运行一个应用程序。很多应用程序需要规律性地定时运行。例如,SquirrelMail 程序创建临时文件,并由定期运行的 tmpwatch 工具删除它。在 Redhat 和 SuSE 发行版中,下列目录被用于执行定时任务:
* /etc/cron.d/
* /etc/cron.hourly/
* /etc/cron.daily/
* /etc/cron.weekly/
* /etc/cron.monthly/
应用程序可以在这些目录中插入 shell 脚本,这些脚本将被每小时,每天,每周或每月执行一次。需要更灵活的定时的程序可以将 crontab 放在 /etc/cron.d/ 目录。在打包需要定时运行某个命令的应用程序时,必须创建合适的文件,放在其中某个目录中。
类似的,一些应用程序需要 shell 或者环境的修改。打包时进行这些修改的 shell 脚本可以放在 /etc/profile.d/ 目录。
会生成日志文件的程序需要保证日志文件可以定期得到轮换,因此应当将一个进行设置的文件放在 /etc/logrotate.d/ 目录中。
需要在系统启动时运行的守护进程需要创建一个初始化脚本。大多数守护进程需要的是一个 System V 启动脚本,而采用超级进程启动的守护进程需要创建的是一个 xinetd 或是 inetd 初始化脚本。
一些程序需要更多配置。基于 X 的应用程序需要向 X 环境中的菜单系统添加条目,因此需要提供一个配置文件,向菜单结构中添加它们。Web 应用程序和 Apache 模块总是需要对 Apache web 服务器的配置进行修改,因此需要配置文件来修改 Apache web 服务器的行为。进行认证的应用程序需要为 PAM 子系统提供配置文件。
Page 14
创建 System V 初始化脚本
独立的守护进程 chkconfig
使用 System V 初始化脚本允许使用标准的方法来管理独立的守护进程,运行:
# /etc/init.d/script name (start|stop|restart)
在为守护进程创建 RPM 的时候,最好创建并安装 SysV 初始化脚本,这样系统管理员可以像管理其他系统自带的守护进程一样,管理它们。
在创建 SysV 初始化脚本的时候,可以基于已有的,简单的脚本,做出必要的修改。在 rhel/fc 中可以参考 /etc/init.d/smartd,在 SLES/SL 中提供了 /etc/init.d/skeleton。
rhel/fc 中,SysV 初始化脚本的官方文档可以在 /usr/share/doc/initscripts-*/sysvinitfiles 文件中找到,而 SLES/SL 中,可以查看 /etc/init.d/README。
chkconfig 命令允许系统管理员容易地控制守护进程应当在哪些运行级启动。例如:
# chkconfig --level 2345 httpd on
要启用这一控制,SysV 初始化脚本的开始必须有特殊的两行,例如:
#!/bin/bash
#
# startup script for the Apache Web Server
#
# chkconfig: 2345 85 15
# description: Apache is a World Wide Web server.
#
首先,chkconfig: 这一行表示,这个守护进程默认应当在运行级 2, 3, 4 还有 5 启动,启动顺序是 85,结束顺序是 15。如果在任何运行级都不应自动启动服务,那么在运行级处使用负号,不要使用数字。这种情况下,安装 RPM 之后,系统管理员可以用
# chkconfig scriptname on
来注册 SysV 初始化脚本。
在 RPM spec 文件中,在 post 安装后脚本部分,应当用这个命令来注册 SysV 初始化脚本:
/sbin/chkconfig --add scriptname
Page 15
创建菜单
freedesktop.org 桌面菜单规约 .desktop 文件
用 RPM 打包应用程序时,最好为它创建一个菜单入口,这样用户可以容易地找到并执行它。
历史上,GNOME 和 KDE 桌面使用自己不同的菜单,菜单文件有不同的格式。发现这个问题后,两个组织走到一起,创建了桌面入口标准。
标准定义了目录 /usr/share/applications/ 为每个菜单入口定义了一个 XML 文件,文件名是 applicationname.desktop
创建了 .desktop 文件之后,可以用 desktop-file-install 命令安装它。这个文件可以用 desktop-file-validate 命令来验证。
对于基本的没有提供描述译文的 .desktop 文件,可以直接在打包的 spec 文件中定义并创建它。
.desktop 文件的完整结构和规则可以在这里找到:
http://standards.freedesktop.org/menu-spec/latest/
spec 文件范例,如何生成和安装 .desktop 文件
%install
......
# 创建菜单入口
cat > %{name}.desktop <
Name=BZFlag
Comment=%{summary}
Exec=%{name}
Icon=bzflag-m.xpm
Terminal=0
Type=Application
EOF
mkdir -p %{buildroot}%{_datadir}/applications
desktop-file-install --vendor TimRiker --dir %{buildroot}%{_datadir}/applications --add-category X-Red-Hat-Extra --add-category Application --add-category Game %{name}.desktop
Page 16
.spec 文件
定义元信息 编译 安装 脚本
创建了所需的补丁文件和辅助文件之后,必须创建一个 spec 文件。spec 文件是以一种混合了宏语言、shell 命令以及描述文本的方式书写的。在 spec 文件中,数字符号 (#) 用来表示注释,与绝大多数其他 Unix 配置文件中是一样的。
spec 文件包含几个紧密相关的段落:
* Header 头部
* Prep 准备
* Build 构建
* Install 安装
* Files 文件
* Scripts 脚本
* Changelog 变更记录
总之,这些段落定义了构成应用程序的源文件和补丁,提供了源代码以及应用程序用途的详细信息,指示 RPM 如何编译,定义了 RPM 在安装时需要安装的文件,以及如何安装它们。spec 文件也包含可选的脚本,可以分别在安装过程和卸载过程的前后执行。
Page 17
构建 RPM 过程中涉及到的目录和文件
foo.spec
Summary: The world famous foo
Name: foo
Version: 1.03
Release: 1
License: GPL
Group: Application/System
Source0: foo-%{version}.tar.bz2
Source1: foo.sysinit
Patch0: foo-fix1.patch
Patch1: foo-fix2.patch
BuildRoot: /var/tmp/%{name}-root
%description
This foo daemon serves bar clients.
%prep
%setup -q
%build
%configure
make
%install
rm -rf %{buildroot}
%makeinstall
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root)
/etc/init.d/foo
%{_sbindir}/foo
/usr/share/man/man8/foo.8
%files devel
%defattr(-,root,root)
/usr/include/foo.h
/usr/lib/foo.a
%changelog
* Mon Apr 30 2003 Dax Kelson
- ver 1.03
1. %prep
* 将文件 (SOURCES/) 解压到构建目录 (BUILD/)
* 打补丁 (SOURCES/ => BUILD/)
2. %build
* 配置 (BUILD/)
* 编译 (BUILD/)
3. %install
* 创建虚拟根文件系统 (/var/tmp/foo-root/)
* 将编译后的二进制文件和相关文件复制到虚拟根分区中的安装位置 (BUILD/ => /var/tmp/foo-root/)
4. %files
* 指定虚拟根分区中,要打包到不同的 RPMs 中的文件 (/var/tmp/foo-root/ => RPMS/i386)
Page 18
使用宏
在 RPM 中大量使用了宏,来进行配置。配置宏可以设置为全局的,只要放在 /usr/lib/rpm/macros 配置文件中。也可以进行个人设置,当 RPM 的任何命令执行时,会查找配置文件 $HOME/.rpmmacros,文件中所定义的任何配置指令将覆盖全局的配置选项。
宏也常常用在 spec 文件中。在 spec 文件中常用的命令都有预先定义的宏,很多系统中常用的目录和路径也有预先定义的宏。
在配置文件和 spec 文件中,为宏名称赋值的方法是,首先写出宏名称,接着写出值。例如,$HOME/.rpmmacros 中下面的语句
%_topdir /export/home/rpmmaker/rpmbuild
将 /export/home/rpmmake/rpmbuild 赋给宏 %_topdir。
在配置文件和 spec 文件中,宏的值可以这样引用,只要将宏名称包含在花括号中就可以了。例如,任何时候宏 %{_topdir} 出现在 spec 文件中时,对于设定了这个宏的用户,它将被自动替换为值 /export/home/rpmmaker/rpmbuild
由于宏在书写 spec 文件时如此有用,很多发行版销售商提供了很多预定义的宏,可以在书写 spec 文件时使用。在 Redhat 发行版中,这些销售商自定义的宏放在 /etc/rpm 子目录。在 SuSE 发行版中,这些销售商自定义的宏放在 /usr/lib/rpm/suse_macros 文件中。另外,/usr/lib/rpm 目录中的配置文件定义了很多标准的宏。在为多种发行版构建打包时,必须小心不要使用销售商自定义的宏。
Page 19
常用的宏
%_prefix /usr
%_exec_prefix %{_prefix}
%_bindir %{_exec_prefix}/bin
%_sbindir %{_exec_prefix}/sbin
%_libexecdir %{_exec_prefix}/libexec
%_datadir %{_prefix}/share
%_sysconfdir %{_prefix}/etc
%_sharedstatedir %{_prefix}/var
%_lib lib
%_libdir %{_exec_prefix}/%{_lib}
%_includedir %{_prefix}/include
%_oldincludedir /usr/include
%_infodir %{_prefix}/info
%_mandir %{_prefix}/man
%configure \
CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS; \
CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS; \
FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS; \
./configure --host=%{_host} --build=%{_build} \\\
--target=%{_target_platform} \\\
--program-prefix=%{?_program_prefix} \\\
--prefix=%{_prefix} \\\
--exec-prefix=%{_exec_prefix} \\\
--bindir=%{_bindir} \\\
--sbindir=%{_sbindir} \\\
--sysconfdir=%{_sysconfdir} \\\
--datadir=%{_datadir} \\\
--includedir=%{_includedir} \\\
--libdir=%{_libdir} \\\
--libexecdir=%{_libexecdir} \\\
--localstatedir=%{_localstatedir} \\\
--sharedstatedir=%{_sharedstatedir} \\\
--mandir=%{_mandir} \\\
--infodir=%{_infodir}
%makeinstall \
make \\\
prefix=%{buildroot}%{_prefix} \\\
exec_prefix=%{buildroot}%{_exec_prefix} \\\
bindir=%{buildroot}%{_bindir} \\\
sbindir=%{buildroot}%{_sbindir} \\\
sysconfdir=%{buildroot}%{_sysconfdir} \\\
datadir=%{buildroot}%{_datadir} \\\
includedir=%{buildroot}%{_includedir} \\\
libdir=%{buildroot}%{_libdir} \\\
libexecdir=%{buildroot}%{_libexecdir} \\\
localstatedir=%{buildroot}%{_localstatedir} \\\
sharedstatedir=%{buildroot}%{_sharedstatedir} \\\
mandir=%{buildroot}%{_mandir} \\\
infodir=%{buildroot}%{_infodir} \\\
install
Page 20
常用的头部字段
Name, Version, Release, License, Group, Source, Patch, URL, Requires, BuildRequires
Head 段落通常是 spec 文件的第一段。它提供了要打包的应用程序的信息。头部的字段包括:
* Name - 应用程序的名称
* Version - 应用程序的版本
* Release - 打包的修订版本
* License - 许可方式 (警告:不要用 Copying 或者 Copyright.)
* Group - 应用程序所属的组
* Source - 应用程序的源代码
* Patch - 应用程序的补丁
* URL - 应用程序原始代码的位置
* Requires - 应用程序运行所必需的软件
* BuildRequires - 编译应用程序时必需的软件
Group 字段有效的取值可以在 Redhat 发行版的 /usr/share/doc/rpm-*/GROUPS 文件中找到。
通常,一个 RPM 会需要多于一个 Source 文件和/或 Patch 文件。这时,Source 和 Patch 字段只要简单地编号:
Source0:
Source1:
Patch0:
Patch1:
Requires 和 BuildRequires 字段是可选的。RPM 会在构建时自动计算软件的依赖性关系。Requires 字段允许开发者列出运行时依赖关系,如果他们需要的话。类似的,BuildRequires 字段用来指定为正确编译,必须安装的软件。尽管不常用,指出任何不明显的构建依赖,警告试图编译软件的人,还是礼貌的做法。Requires 和 BuildRequires 都可以列出它们需要的软件名称,如果需要特定的版本,就列出名称和版本号。
头部通常还有两个字段。Summary 字段用来提供要打包的应用程序的短的,一行的自荐性描述,而 %description 字段提供很长的,可能分为多个段落的描述。
如果要在 spec 文件中创建,定义使用自定义宏,它们通常放在头部。
Page 21
高级的头部字段 Arch, Epoch
特殊情况下会在头部使用其他的字段。很多 Architecture 选项可以用来控制软件包构建的体系结构。BuildArch 用来强制软件包为特定体系结构构建,而不是为构建过程所在的平台的默认体系结构。通常,它用来指示所构建的打包是一个 .noarch.rpm:
BuildArch: noarch
并不是所有软件都能在任何平台中编译,就好像并不是所有软件都能在任何体系结构中运行一样。两个指令可以用来强制这些要求。ExclusiveArch 可以用来列出支持这一软件的平台,在其他平台中 RPM 将不会编译它。ExcludeArch 可以用来列出不支持这一软件的平台,RPM 在其他平台中才会编译它。语句
ExcludeArch: s390 s390x
表示软件应当在除了 31 位和 64 位的 s/390 硬件之外的那些机器上构建,而语句
ExclusiveArch: i386 s390 s390x x86_64
表示软件包应当只在 32 位 x86 硬件,31 位和 64 位 s/390 硬件以及 64 位 AMD (Opteron) 硬件中构建,但不在任何其他系统中构建。
RPM 在头部还提供了 Epoch 字段。通常,RPM 软件使用软件包版本和发行标记来判断一个软件包是否比另一个要新。一些软件使用非标准的版本号,或者改变了版本命名。例如,Postfix MTA 过去使用 YearMonthData 作为版本号 (类似于 postfix-19990906.tar.gz)。最近,Postfix 的作者采用了更为传统的双数位版本命名系统 (类似于 postfix-2.0.9.tar.gz)。在 RPM 比较 19990906 与 2.0.9 的时候,19990906 显然要更新 (版本号更高),尽管实际上它出现四年后,postfix-2.0.9 才发布。要更正这些问题,RPM 使用 Epoch 字段。通常,如果不出现,这个字段被认为是 0,如果需要时可以设置为一个更高的值。当比较版本号时,RPM 首先比较 Epoch,其次是 Version,最后是 Release。因此,Postfix 打包在 Epoch 为 1,Version 为 2.0.9 时,就比 Epoch 为 0,Version 为 19990906 的打包要新了。
Page 22
Prep 段落 准备工作
在 Header 头部之后,下一段落通常是 Prep。这一段落总是以标识 %prep 开始,用来准备要编译的软件。通常,这一段落将归档中的源代码解压,并应用补丁。这些可以用标准的 shell 命令完成,但是更多地使用预定义的宏。
常见的一个宏是 %setup。
这个宏解压源代码,将当前目录改为源代码解压之后产生的目录。这个宏还有一些选项可以用。例如,在解压后,%setup 宏假设产生的目录是
%{name}-%{version}
如果 tar 打包中的目录不是这样命名的,可以用 -n 选项来指定要切换到的目录。例如:
%setup -n %{name}-April2003Rel
另一个 %setup 常用的选项是 -q,它将 tar 命令的繁复输出关闭。
这里常见的另一个宏是 %patch。
这个宏将头部定义的补丁应用于源代码。如果定义了多个补丁,它可以用一个数字的参数来指示应用哪个补丁文件。它也接受 -b extension 参数,指示 RPM 在打补丁之前,将文件备份为扩展名是 extension 的文件。
下面的宏
%patch2 -b .test
指示 RPM 应用 Patch2,将任何要修改的文件备份为扩展名是 .test 的文件。
%patch 宏的 -p 选项控制着要传给 /usr/bin/patch 命令的 -p 选项。通常,会使用 -p1,但是,这当然依赖于补丁文件是如何创建的。
Page 23
构建
在 Prep 段落之后,spec 文件通常包含一个 Build 段落,总是以 %build 标识开始。
在这个段落中,包含用来配置和编译已配置的软件的命令。与 Prep 段落一样,这些命令可以是 shell 命令,也可以是宏。
如果要编译的宏使用了 autoconf,那么应当用 %configure 宏来配置软件。这个宏自动为 autoconf 指定了安装软件的正确选项,编译优化的软件。
如果软件不是用 autoconf 配置的,那么使用合适的 shell 命令来配置它。
软件配置之后,必须编译它。由于各个应用程序的编译方法都各自不同,没有用来编译的宏。只要写出要用来编译的 shell 命令就可以了。
环境变量 $RPM_OPT_FLAGS 在编译软件时很常用。这个 shell 变量包含针对 gcc 编译器套件的正确的优化选项,使用这样的语法:
make CC="gcc $RPM_OPT_FLAGS"
或者
make CFLAGS="$RPM_OPT_FLAGS"
就可以保证总是使用合适的优化选项。也可以使用其他编译器标志和选项。默认的 $RPM_OPT_FLAGS 是:
-O2 -g -march=i386 -mcpu=i686
Page 24
Install 段落
在 Build 段落之后,是 Install 段落。这个段落总是以标记 %install 开始。
这个段落用于将已编译的软件安装到虚拟的目录结构中,从而可以打包成一个 RPM。
在 Header 段落,可以定义 Buildroot,它定义了虚拟目录树的位置,软件将安装到那里。通常,它是这样的:
Buildroot: %{_tmppath}/%{name}-root
或是
Buildroot: %{_tmppath}/%{name}-%{version}-root
使用 RPM 内建的宏来指定 /var/tmp 目录中一个私用的目录。
在 spec 文件的其余部分可以用 shell 变量 $RPM_BUILD_ROOT 获取 Buildroot 的值。
mkdir -p $RPM_BUILD_ROOT/usr/share/icons/
cp %{SOURCE3} $RPM_BUILD_ROOT/usr/share/icons/
Install 段落通常列出要将已编译的软件安装到 Buildroot 中的命令
宏 %makeinstall 可以用于安装支持 autoconf 的软件。这个软件自动地将软件安装到 $RPM_BUILD_ROOT 下的正确的子目录中。
有时,软件包必须被构建多次,由于打包错误或其他原因。每次构建时,Install 段落将复制文件到 Buildroot 中。要防止由于 Buildroot 中的旧文件而导致错误的打包,必须在安装新文件之前将 Buildroot 中任何现有的文件删除。为此,可以使用一个 clean 脚本。这个脚本通常以 %clean 标记表示,通常仅仅包含这样一句:
rm -rf $RPM_BUILD_ROOT
如果有的话,在制作了在 Install 段落中安装的文件的打包之后,将运行 %clean,保证下次构建之前 Buildroot 被清空。
Page 25
Files 段落
在 Install 段落之后,下一个段落是 Files,列出了要打包到一个 RPM 中的文件和目录。这个段落通常以标记 %files 开始。在这个段落中,每行一个,简单地列出文件和目录,相对于 Bduilroot,它们将被存档到打包中。可以在这里使用通配符,例如
/usr/bin/*
指示 RPM 将 $RPM_BUILD_ROOT/usr/bin 目录中所有文件打包。
在列出文件和目录时,必须小心列出所有需要的文件,不要列出任何不应被打包的文件。在列出一个目录时要更加小心。列出一个目录意味着 RPM 要打包这个目录以及其中的所有文件,因此语句
/usr/bin
指示 RPM 将 $RPM_BUILD_ROOT/usr/bin 目录中所有文件打包,但是也会创建一个似乎拥有 /usr/bin 目录的不正确的打包。
在 Files 段落,有一些宏可以用。应当总是应用 %defattr 宏来指定之后列出文件的默认的所有者和权限。例如,语句 %defattr(0770,root,root) 将定义其后列出的所有文件和目录,直到下一个 %defattr 为止,它们在安装后的所有者是 root.root,拥有权限 0770。另外,单独的文件可以用 %attr 指定与 %defattr 不同的所有者和权限。例如:
%files
%defattr(-,root,root)
%{_libdir}/libamanda*.so
%attr(660,amanda,disk) /var/lib/amanda/.amandahosts
一些宏用来指示要安装的文件具有特殊的属性。宏 %dir 可以用来指示要打包的是一个目录,而不是目录中的文件。宏
%config(noreplace)
用来指示被安装的是一个配置文件,在软件包升级时不应被覆盖。
Page 26
可选的脚本段落
有时需要在安装的前后,在系统中运行一些命令。例如,在安装了新的动态链接库之后,应当运行 ldconfig 命令来使系统使用新安装的库。
RPM spec 文件可以包含分别在安装和卸载前后运行的脚本。这些脚本通常在 Files 段落之后列出,是简单的 Bourne shell 脚本,列在一个指示它们何时执行的宏后面。可用的值为:
* %pre - 安装前执行
* %post - 安装后执行
* %preun - 卸载前执行
* %postun - 卸载后执行
最常见的,这些命令用在需要使用新系统帐号才能运行的软件打包中。%pre 脚本可以用来添加需要的帐号,%postun 可以用来在卸载软件时删除这个不再需要的帐号。在 Redhat 系统中准备需要用户帐号的打包时,参考 /usr/share/doc/setup-*/uidgid 文件,它列出了 Redhat 附带的软件已经使用了的 UIDs 和 GIDs。
有时,需要在 %pre, %post, %preun 和 %postun 中执行的脚本是随机的,要根据当前系统中软件的安装情况进行抉择。例如,Mailman 邮件列表管理程序需要一些邮件别名才能工作,因此它的打包需要在 %post 脚本中,向系统添加一些邮件别名,在 %postun 脚本中移除它们。这些别名要写入的位置是随系统中安装的 MTA 而不同的——postfix 使用文件 /etc/postfix/aliases 作为别名数据库,而 Sendmail 使用文件 /etc/aliases 作为别名数据库。
这种情况下,要采用的动作取决于当前系统状态的话,可以用 shell 脚本的条件判断。不过,RPM 提供了一种触发机制,可以用来在其他软件安装/卸载时执行动作。这些脚本以
%triggerin -- package
还有
%triggerun -- package
标记。第一个标记表示软件 package 安装或升级时运行的脚本,而第二个表示软件 package 卸载时运行的脚本。
Page 27
Changelog 段落
spec 中的最终段落是 Changelog 段落。这个段落总是以 %changelog 标记开始,用来列出对打包的任何修改。
尽管日志的结构技术上可以是自由格式,但是大多数 RPM 系统中使用下面的格式:
* 日期 打包人 <打包人的电子邮件> 版本-发行标记
- 所作的更改
- 其他更改
日期必须是下列格式:
Wed Nov 20 2002
这种格式的当前日期可以用命令
date +"%a %b %d %Y"
得到。
每次准备打包的新的修订版时,打包人只要在 Chanlog 段落起始处加上类似的一段。
下列范例是来自 Fedora Core 3 firefox RPM spec:
* Wed Mar 02 2005 Christopher Aillon
- Remerge firefox-1.0-pango-selection.patch
* Thu Feb 24 2005 Christopher Aillon
- Update to 1.0.1 fixing several security flaws.
- Mark some generated files as ghost (#136015)
- Add RPM version to the useragent
- BuildRequires pango-devel
- Enable pango rendering by default
- Enable smooth scrolling by default
Redhat 使用的一个约定是引用它们的错误跟踪系统的错误 Id。在这个例子中,引用了一个有关 RPM 打包的错误。详情可以通过下面的网址查看:
https://bugzilla.redhat.com/bugzilla....cgi?id=136015
Page 28-31
最后的 spec 文件
Page 32
其他内容
除了基本的 spec 文件结构,还有一些高级的需求。通常,一个应用程序需要打包为两个或多个软件包。例如,LessTif 软件包提供了多种不同的内容:一个运行时库,为连接到 Motif 部件集的软件所用,编程的头文件和库文件,开发者用它们来创建应用程序,还有一个窗口管理器。这是三个明显不同的应用程序,不同的用户需要不同的组合。因此, RPM spec 文件可以设定为生成子打包,通过同一个源代码生成两个或多个二进制打包。
另一个常见的需求是在不能获得源代码时,打包二进制文件。例如,Adobe 发布了 Acrobat Reader for Linux,但是在第七版之前,他们只发布二进制可执行文件的 tar 打包。可以为此创建 RPM,允许用户使用 RPM 工具来管理这个程序。要创建这样的 spec 文件,只要简单地省略 Build 段落,在 %install 段落中,手动复制文件到虚拟根文件系统中就可以了。
打包人有时想创建交互式的 RPM,也就是说,在安装过程中询问用户问题。RPM 故意地不支持创建交互的打包!只为保证所有安装过程可以脚本化。要小心设计软件包,避免安装时的交互。
打包人通常需要为多个发行版准备打包。需要考虑一些潜在的复杂情况,才能使单个 spec 文件用于在多个发行版中编译 RPM:
* 不同的发行版预定义了不同的宏。大多数在 Redhat 发行版中定义的宏处于一个 “基线” 上,可以假设绝大多数发行版中也定义了它们,包括 SuSE 发行版。因此,只使用 Redhat 系统中定义的宏,有助于跨发行版的兼容性。
* 不同的发行版使用不同版本的 RPM。旧版本的 Linux 发行版使用旧版本的 RPM 3,而较新的系统使用新的 RPM 4。不同的 RPM 版本中有行为和语法的差别,必须消除。
* 有时不同的发行版将文件安装在不同的位置。Linux Standards Base (LSB) 的努力消除了很多这样的因素,但是还是可能出现。
打包者总会想发布支持多种语言的打包,使用户可以看到以母语显示的打包描述以及相关信息。RPM 提供了一个 specspo 机制,可以用来为打包文件保存已翻译的消息。
Page 33
构建软件包
当准备好 spec 文件之后,接下来是使用 spec 文件构建软件。基本的构建命令,在较新的系统中是 rpmbuild -b spec,在过去的系统中是 rpm -b spec。这个命令支持下面各种不同的参数,取决于要处理 spec 文件的哪一部分:
* -bp - 处理 spec 文件的 Prep 部分
* -bc - 处理 spec 文件的 Prep 和 Build 部分
* -bi - 处理 spec 文件的 Prep, Build 和 Install 部分
* -bl - 校验 spec 文件的 Files 部分
* -bb - 根据 spec 文件构建二进制 RPM
* -bs - 根据 spec 文件构建源代码 RPM
* -ba - 根据 spec 文件同时构建二进制 RPM 和源代码 RPM
最常用的是
rpmbuild -ba spec
有时会用 --target 参数来强制 RPM 为特定的平台编译软件。例如,在 32 位 x86 系统,运行 rhel/fc 的平台中,RPM 默认生成运行在任何 32 位 x86 计算机上的打包,但是对于 80686 级别的计算机会做优化。这个选项可以用来强制 RPM 生成只在 80686 级别的计算机中运行的,或是为 AMD Athlon 更好优化过的,或是为 80386 级别的计算机优化过的打包。命令
rpmbuild -ba --target i686-redhat-linux spec
根据 spec 构建 RPM,只与 80686 级别的机器兼容,比默认的 RPM 优化要稍微更好一点。
在构建打包时,RPM 提供在命令行覆盖或修改 RPM 宏的能力。打包人通常用这个特性来生成可以用来编译相同的软件,但是使用不同选项的 spec。例如,rhel/fc 的 Postfix spec 在 Header 段落包含了各种宏定义,在编译期启用或禁用支持各种特性。这个语句
%define LDAP 0
用来定义 LDAP 的值为 0,在后面 Build 段落中的命令使用这个变量来编译不带 LDAP 支持的 Postfix。使用这样的命令行来覆盖这个变量的值:
rpmbuild -ba --define ‘LDAP 1‘ postfix.spec
Postfix 在编译时就有了 LDAP 支持。
Page 34
数字签名的软件包
由 spec 文件创建了二进制和源代码 RPM 之后,可以使用 GPG 或 PGP 为结果 RPM 签名。签名为下载软件包的最终用户提供了两个重要的功能:
* 它们证明软件包可信,向用户保证,打包来自它应该来自的地方。
* 它们保证打包的完整性,向用户保证软件包在打包人签名之后,没有遭到修改 (尽管 RPM 还通过其他机制提供了这一保证)
这些特性在当今木马横行的互联网上都非常重要。
要签署一个打包,必须首先有一个 GPG 密钥。如果没有的话,可以很容易地生成一个:
$ gpg --gen-key
生成密钥之后,修改你的 RPM macros 来指示 RPM 使用 GPG 签署打包:
echo "%_signature gpg" >> $HOME/.rpmmacros
同时,指定 RPM 应当使用哪个密钥来签署打包:
echo "%_gpg_name 邮件地址" >> $HOME/.rpmmacros
最后,指定 RPM 如何定位你的 GPG 密钥:
echo "%_gpg_path $HOME/.gnupg" >> $HOME/.rpmmacros
配置好 RPM 使用 GPG 之后,可以用 rpmsign 命令来签署你构建的打包:
$ rpmsign --addsign /path/to/the.rpm
可以导出你的公钥:
$ gpg --export --armor > gpg-pub-key
然后将公钥发给安装你的 RPM 的用户,他们可以用它来校验你的 RPM 是由你签署的。要做到这一点,他们必须首先导入你的 GPG 公钥到他们的 RPM GPG 钥匙环中:
# rpmsign --import /path/to/gpg-pub-key
导入公钥之后,可以校验打包的签名了:
$ rpmsign -K package-1.0-1.i386.rpm
package-1.0-1.i386: (sha1) dsa sha1 md5 gpg OK
如果打包通过校验,那么用户就知道它的签名来自他们信任的一方了。
Page 35
修订打包
除创建新的 RPM 之外,打包人另一个经常性的任务是更新现有的打包,在应用程序有新的版本可用时重建打包。修正现有的源代码 RPM 只要很简单的几步:
1. 安装最新的 SRPM
2. 将应用程序的最新的源代码放在 SOURCES 目录
3. 修改 spec 文件为使用最新的源代码
4. 试着做 spec 文件的 Prep 段落:
$ rpmbuild -bp application.spec
在尝试的时候可能会发现,一些补丁不再适用于新版本的源代码了。这时,查看补丁文件的内容,以及应用程序的源代码,检查为什么不适用。
1. 补丁无法应用,是因为不再需要了。这时,只要从 spec 文件中移除补丁就可以了
2. 补丁仍然需要,但是无法应用,因为应用程序的代码在其他部分发生了变化。这时,创建一个新版本的补丁,使它可以适用于新版本的源代码
可以成功完成 Prep 段落之后,更新 spec 文件中的 Changelog 段落以及版本信息,然后构建新打包:
$ rpmbuild -ba application.spec
Page 36
其他资源
有很多资源,提供了更多有关 RPM 和如何创建 RPM 的信息。最好的资源是 http://www.rpm.org ,提供了各种有关 RPM 的文档,以及 RPM 的源代码。这个站点有一本免费下载的书,《Maximum RPM》。尽管它有些过时,但是仍然是不错的补充资源。
很多工具可以简化 RPM 的创建,包括文本编辑器的 spec 文件编辑模式:
http://www.tihlde.hist.no/~stigb/rpm-spec-mode.el
http://pegasus.rutgers.edu/~elflord/vim/syntax/spec.vim
还有各种生成 spec 文件的工具:
http://rpmrebuild.sourceforge.net
http://www.cpan.org/modules/by-modul...le-1.17.tar.gz
http://checkinstall.izto.org
为多个系统准备打包的主要困难是需要有为每个系统准备独立的构建环境。有很多程序可以用来简化在同一台机器上创建多个构建环境:
http://thomas.apesstaart.org/projects/mach
http://www.solucorp.qc.ca/miscprj/s_context.jc
一些网站提供各种高质量的编译好的 RPM,也可以用来寻找已有的 RPM:
http://freshrpms.net
http://www.fedoraproject.org
http://www.rpmfind.net
http://www.GuruLabs.com/downloads.html
有很多工具可以用来简化安装 RPM 的工作,包括:
http://current.tigris.org
http://www.linux.duke.edu/projects/yum
http://www.autorpm.org
http://www.mat.univie.ac.at/~gerald/autoupdate
http://apt4rpm.sourceforge.net
http://www.smartpm.org
实验
任务 1 (6 小题) (p.39-p.42)
任务 2 (10 小题) (p.43-p.51)
任务 3 (53 小题) (p.52-p.79)
任务 4 (13 小题) (p.80-p.86) RPM Builder 能够将tar.gz 格式的文件转换为RPM 格式的包。它可以自动的产生所必需的RPM 格式文件摸板,然后创建RPM 格式文件和SRPM 格式文件。即使你不了解RPM 包,你也可以使用这个软件创建一个RPM 包。
http://download.enet.com.cn/html/262392001011002.html
rpmbuilder 的下载地址
Clear River Technologies
http://www.klabs.net/rpmbuilder/
Guru Labs《Creating RPMs (Student version)》v1.0 (创建 RPM 打包,学生版)
Guru Labs《Creating RPMs (Student version)》v1.0 (创建 RPM 打包,学生版)
用 RPM 打包软件
Version 1.36.0
rpm
Version 1.5.0 or 5.0?
Version 1.5.0 or 5.0?
尼康Capture NX V1.0版印象
WinTSBSA v1.0
7.0版女友程序V1.0版太太程序
新概念技术 GHOST XP SP3 纯净版 V1.0
教育系列合集典藏版V1.0
百度手机输入法下载 百度输入法 V1.0 手机版
野蔷薇社区论坛YeQiangWeiClub v1.0 M2 源码版
创建学习型班级-黄河科技学院学生-
eKMS概述 - BenQ Guru
硬盘安装器 V1.0
smile?for?stock?v1.0
南京校园电视网 v1.0
美国野兽 - Passat 3.6 US Version(北美版)
sub version
Possible version
rpm详解
RPM Guide