RPM 使用与 SPEC 文件

1. 概述

RPM全称是 Red Hat Package Manager(Red Hat包管理器)。

RPM的发布基于GPL协议(GNU通用公共授權條款GNU General Public License,简称GNU GPLGPL)。

RPM有五种基本的操作功能(不包括创建软件包):安装、卸载、升级、查询、和验证。关于rpm命令的使用我们可以用以下命令:

1
[root@serverwyq wyq]# rpm --help

​ 通常,供Linux使用的源代码包还提供一个名为 { 软件名称 }.spec 的文件,即spec文件。如果提供spec文件,则该源代码还可以直接编译成RPM包。

2. RPM 使用

1)安装

1
rpm {-i|--install} [install-options] PACKAGE_FILE ...

​ 通过rpm -ivh可以把rpm软件包安装到系统中,使用的较多的是-ivh参数 ,使用该选项可以解决大部分rpm软件包的安装,至于详细的参数说明可用查看rpm的man 文档。

2)卸载

1
2
3
4
5
6
7
8
9
10
11
rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts]
[--notriggers] [--test] PACKAGE_NAME ...

注:
--nodeps Don’t do a dependency check before installing or upgrading a package.(不检查依赖)
--force Same as using --replacepkgs, --replacefiles, and --oldpackage.(相当于同时使用了这三个参数)

--replacepkgs
Install the packages even if some of them are already installed on this system.
--replacefiles
Install the packages even if they replace files from other, already installed, packages.

​ 如果某个软件包你再也不想使用了,那就用以上这个命令彻底的把你指定的rpm软件包清除掉把。

3)升级

1
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...

​ 由于开源软件更新速度快,用户当然要使用最新版本的软件包,此时最合适的就是rpm升级功能,当然最理想的参数选项就是-Uvh。

4)查询

1
rpm {-q|--query} [select-options] [query-options]

​ 查看软件包的版本、依赖关系等软件包的详细说明都要用到这个选项,常用的有:

rpm -qa 是查询机器上所有已经安装的包,加上grep可以得到你想要的包名

1
2
3
4
[root@serverwyq wyq]# rpm -qa | grep kernel
kernel-...
kernel-devel-...
kernel-headers-...

rpm -qi + 包名 == 查看包的详细信息

1
2
3
4
5
6
[root@serverwyq wyq]# rpm -qi kernel-3.10.0-123.el7.x86_64                                                                                                                                
Name : kernel
Install Date: 2014年07月09日 星期三 13时57分38秒
......
URL : http://www.kernel.org/
Summary : The Linux kernel

rpm -ql + 包名 == 查看包内文件的安装路径

1
2
3
4
5
[root@serverwyq wyq]# rpm -ql kernel-3.10.0-123.el7.x86_64 |more                                                                                                                            
/boot/.vmlinuz-3.10.0-123.el7.x86_64.hmac
/boot/System.map-3.10.0-123.el7.x86_64
/boot/config-3.10.0-123.el7.x86_64
......

5)校验

1
rpm {-V|--verify} [select-options] [verify-options]

​ 一般我们可用通过该命令来验证已安装软件包

6)解压

​ RPM包是使用cpio格式打包的,因此需要先转成cpio然后解压。

1
rpm2cpio some.rpm | cpio -div

3. spec文件

​ 其实,制作RPM软件包并不是一件复杂的工作,其中的关键在于编写SPEC软件包描述文件。

​ 这个文件中包含了软件包的诸多信息,如软件包的名字、版本、类别、说明摘要、创建时要执行什么指令、安装时要执行什么操作、以及软件包所要包含的文件列表等等。

​ 像前面rmp -qi所看的信息都是制作rpm包时在spec文件中指定的。

1)Preamle

​ 序言包含用户请求包的信息时所显示的内容。它可以包含包的功能描述、包的软件版本、版权信息和所属的包组等。Summary 是一行关于该软件包的描述,Name 是该软件包的基名,Version 是该软件的版本号, Release 是 RPM 本身的版本号,如果修复了 spec 文件中的一个错误并发布了该软件同一版本的新 RPM,就应该增加发行版号。License 应该给出一些许可说明,Group 标识软件类型。那些试图帮助人们管理 RPM 的程序通常按照组列出 RPM。您可以在/usr/share/doc/rpm-x.x.x/GROUPS 文件看到一个 Red Hat 使用的组列表。但是您还可以使用那些组名以外的名称。Source0、Source1等等给这些源文件命名(通常为 tar.gz 文件)。%{name} 和 %{version} 是 RPM 宏,它们扩展成为头中定义的 rpm 名称和版本。

​ 要注意的是,不要在 Source 语句中包含任何路径。缺省情况下,RPM 会在 /usr/src/redhat/SOURCES 中(对于Redhat6 系统,则是在 /root/rpmbuild/SOURCES 目录中)寻找文件,请将您的源文件复制或链接到那里。(要使 spec 文件尽量可移植的话,应当尽量避免嵌入自己开发机器上的假想路径。其他开发人员就可以指示 RPM 在别的目录下查找源文件,而不用修改您的 spec 文件。)

​ 接下来的部分从 %description 行开始。您应该在这里提供该软件更多的描述,这样任何人使用 rpm -qi 查询您的软件包时都可以看到它。您可以解释这个软件包做什么,描述任何警告或附加的配置指令,等等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Summary: Utilities for managing accounts and shadow password files.
Name: shadow-utils
Version: 4.0.17
Release: 14%{?dist}

Source0: %{name}-%{version}.tar.bz2
Source1: shadow-4.0.17-login.defs
Source2: shadow-970616.useradd

Patch0: shadow-4.0.17-redhat.patch
Patch1: shadow-4.0.3-noinst.patch
Patch2: shadow-4.0.11.1-vipw.patch

Packager:amoblin
Group: Application
URL: http://www.ossxp.com
License: GPL
BuildRequires: autoconf, automake, libtool, gettext-devel
BuildRequires: libselinux-devel >= 1.25.2-1
BuildRequires: audit-libs-devel >= 1.0.10
Requires: libselinux >= 1.25.2-1

%description
This package includes the necessary programs for XXX.

2)Prep

Prep 部分进行实际的打包准备工作,它是使用节前缀%prep表示的。主要功能有:
​ 1. 将文件 (SOURCES/) 解压到构建目录 (BUILD/)
​ 2. 应用Patch(打补丁) (SOURCES/ => BUILD/)
​ 3. 描述 “rm -rf $RPM_BUILD_ROOT”
​ 4. 描述或编辑本部分用到的命令到 PreReq:
​ 5. 通过 “-b .XXX” 描述补丁备份

%setup

-n newdir #将压缩的软件源程序在newdir目录下解开。
-c #在解开源程序之前先创建目录。
-b num #在包含多个源程序时,将第num个源程序解压缩。
-T #不使用缺省的解压缩操作。

通常patch补丁都会一起放到SOURCES目录下。一般参数为
%patchN -p1 #应用前面定义的第N个patch,-p1是忽略patch的第一层目录

1
2
3
4
5
6
%setup -q   #最常用
%setup -q -n newdir #将source解压至newdir
%setup -T -b 0 #解开第一个源程序文件
%setup -c -n newdir #创建目录newdir,并在此目录之下解开源程序

%patch1 -p1 #应用第1个补丁

eg:

1
2
3
4
5
6
7
8
9
10
%prep
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1

cp %{SOURCE3} lib/nscd.c
rm po/*.gmo
rm po/stamp-po

3)Build

主要用于编译源码,它是使用节前缀%build表示的。一般用于configure及make的过程。

eg:

1
2
3
%build
%configure --with-selinux --without-libpam --disable-shared --with-libaudit
make

4)install

这一节主要用于完成实际安装软件必须执行的命令,它是使用节前缀%install表示的。这一节一般是由make install指令构成,但是有时也会包含cp、mv、install等指令。

这一节还能指定在用户安装的系统上,包安装时运行的脚本。这样的脚本称为安装(卸载)脚本。它可以指定包安装前、包安装后、包除去前、包除去后的系统必须运行的外壳程序段。在用户安装的系统上,为了验证一个包是否已经成功安装的验证脚本也可由这一节指定。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT gnulocaledir=$RPM_BUILD_ROOT/%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs
install -d -m 755 $RPM_BUILD_ROOT/etc/default
install -c -m 0644 %{SOURCE1} $RPM_BUILD_ROOT/etc/login.defs
install -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/etc/default/useradd

ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser
ln -s %{_mandir}/man8/useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8
for subdir in $RPM_BUILD_ROOT/%{_mandir}/{??,??_??,??_??.*}/man* ; do
test -d $subdir && test -e $subdir/useradd.8 && echo ".so man8/useradd.8" > $subdir/adduser.8
done

# Remove binaries we don't use.
rm $RPM_BUILD_ROOT/%{_bindir}/chfn
rm $RPM_BUILD_ROOT/%{_bindir}/chsh

5)clean

这一节所描述的内容表示在完成包建立的工作之后,自动执行此节下的脚本进行附加的清除工作,它是使用节前缀%clean表示的。一般而言,这一节的内容是简单地使用rm -rf $RPM_BUILD_ROOT命令,不需要指定此节的其它内容。

eg:

1
2
%clean
rm -rf $RPM_BUILD_ROOT

6)files

这一节指定构成包的文件的列表,它是使用节前缀%files表示的。此外,它还包含一系列宏控制安装后的文件属性和配置信息。

%files 列出应该捆绑到 RPM 中的文件,并能够可选地设置许可权和其它信息。在 %files 中,您可以使用 %defattr 来定义缺省的许可权、所有者和组;%defattr(-,root,root) 会安装 root 用户拥有的所有文件,使用当 RPM 从构建系统捆绑它们时它们所具有的任何许可权。

可以用 %attr(permissions,user,group) 覆盖个别文件的所有者和许可权。可以在 %files 中用一行包括多个文件。可以通过在行中添加 %doc 或 %config 来标记文件。%doc 告诉 RPM 这是一个文档文件,因此如果用户安装软件包时使用 –excludedocs,将不安装该文件。您也可以在 %doc 下不带路径列出文件名,RPM 会在构建目录下查找这些文件并在 RPM 文件中包括它们,并把它们安装到 /usr/share/doc/%{name}-%{version}。以 %doc 的形式包括 README 和 ChangeLog 这样的文件是个好主意。

%config 告诉 RPM 这是一个配置文件。在升级时,RPM 将会试图避免用 RPM 打包的缺省配置文件覆盖用户仔细修改过的配置。

注意:如果在 %files 下列出一个目录名,RPM 会包括该目录下的所有文件。通常这不是您想要的,特别对于 /bin 这样的目录。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
%files
%defattr(-,root,root) #指定默认权限
%doc NEWS doc/HOWTO README
%dir /etc/default
%attr(0644,root,root) %config(noreplace) /etc/login.defs
%attr(0600,root,root) %config /etc/default/useradd
%{_bindir}/sg
%{_bindir}/chage
%attr(0750,root,root) %{_sbindir}/user*
%attr(0750,root,root) %{_sbindir}/group*
%{_sbindir}/grpck
%{_sbindir}/pwck
%{_sbindir}/*conv

7)changlog

主要描述软件的开发记录,它是使用节前缀%changlog表示的。对于包的维护极有好处

1
2
%changlog
...

8)example & summer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Summary:    hello world rpm package  
Name: hello
Version: 0.1
Release: 1

License: GPL
Source: %{name}-%{version}.tar.gz
Packager: amoblin
Group: Application
URL: http://www.ossxp.com

%description

%prep
%setup -q

%build

%install
mkdir -p $RPM_BUILD_ROOT/%{_bindir}
gcc -o hello hello.c
install -c -m 755 hello $RPM_BUILD_ROOT/%{_bindir}

%files
%{_bindir}/hello

%clean
rm -rf $RPM_BUILD_ROOT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
(1)Preamle
Summary:
用一句话概括该软件包尽量多的信息。
Name:
软件包的名字,最终RPM软件包是用该名字与版本号,释出号及体系号来命名软件包的。
Version:
软件版本号。仅当软件包比以前有较大改变时才增加版本号。
Release:
软件包释出号。一般我们对该软件包做了一些小的补丁的时候就应该把释出号加1。
Vendor:
软件开发者的名字。
Copyright:
软件包所采用的版权规则。具体有:GPL(自由软件),BSD,MIT,Public Domain(公共域), Distributable(贡献),commercial(商业),Share(共享)等,一般的开发都写GPL。
Group:
软件包所属类别,具体类别在/usr/share/doc/rpm-x.x.x/GROUPS这里可以看到
Source:
源程序软件包的名字。如 stardict-2.0.tar.gz。
%description:
软件包详细说明,可写在多个行上。

(2)%prep段

这个段是预处理段,通常用来执行一些解开源程序包的命令,为下一步的编译安装作准备。%prep和下面的%build,%install段一样,除了可以执行RPM所定义的宏命令(以%开头)以外,还可以执行SHELL命令,命令可以有很多行,如我们常写的tar解包命令。

(3)build段

本段是建立段,所要执行的命令为生成软件包服务,如make 命令。

(4)%install段

本段是安装段,其中的命令在安装软件包时将执行,如make install命令。

(5)%files段

本段是文件段,用于定义软件包所包含的文件,分为三类--说明文档(doc),配置文件(config)及执行程序,还可定义文件存取权限,拥有者及组别。

(6)%changelog段

本段是修改日志段。你可以将软件的每次修改记录到这里,保存到发布的软件包中,以便查询之用。每一个修改日志都有这样一种格式:第一行是:* 星期 月 日 年 修改人 电子信箱。其中:星期、月份均用英文形式的前3个字母,用中文会报错。接下来的行写的是修改了什么地方,可写多行。一般以减号开始,便于后续的查阅。

4. 打包

​ 如果想发布rpm格式的源码包或者是二进制包,就要使用rpmbuild工具。

​ 如果我们已经根据本地源码包的成功编译安装而写了spec文件(该文件要以.spec结束),那我们就可以建立一个打包环境,也就是目录树的建立。

​ 一般是在目录下建立5个目录。它门分别是BUILD、SOURCE、SPEC、SRPM、RPM。

​ - 其中BUILD目录用来存放打包过程中的源文件,

​ - SOURCE用来存放打包是要用到的源文件和patch,

​ - SPEC用来存放spec文件,

​ - SRPM、RPM分别存放打包生成的rpm格式的源文件和二进制文件。

我们可以根据需要来选用不同的参数打包文件:

1) 只生成二进制格式的rpm包

1
rpmbuild -bb xxx.spec

​ 用此命令生成软件包,执行后屏幕将显示执行信息,生成的文件会在刚才建立的RPM目录下存在。

2)只生成src格式的rpm包

1
rpmbuild -bs xxx.spec

​ 生成的文件会在刚才建立的SRPM目录下存在。

3) 只需要生成完整的源文件

1
rpmbuild -bp xxx.spec

​ 源文件存在目录BUILD下。读者朋友可能对这个命令不太明白,这个命令的作用就是把tar包解开然后把所有的补丁文件合并而生成一个完整的具最新功能的源文件。

4) 完全打包

1
rpmbuild -ba xxx.spec

​ 产生以上3个过程分别生成的包。存放在相应的目录下。

​ 软件包制作完成后可用rpm命令查询,看看效果。如果不满意的话可以再次修改软件包描述文件,重新运行以上命令产生新的RPM软件包。

end


https://www.ibm.com/developerworks/cn/linux/l-rpm/

https://www.zhukun.net/archives/7263


昔我往矣,杨柳依依;今我来思,雨雪霏霏