关于制作RPM包的笔记~
一.制作RPM包教程
源码包的制作教程基于RHEL 5 & 6,当我写这个的时候还没有7版本,我会在后续更新新版本的路数.
1. rpm包的制作流程简述
- 放置源码进入SOURCES文件夹
- 写好SPEC文件
- 运行rpmbuild命令,自动执行安装和清理
- 自动将所有的源码解压到BUILD目录
- 自动安装所有的源码程序到BUILDROOT目录
- 自动根据SPEC文件里面的file程序段打包到rpm包中
- 自动进行后续的清理
- 生成完整的RPM包
- 手动进行安装测试
2. 如何做准备
需要明确的几个问题:
- 我们需要做一个什么样的RPM包,这个RPM包使用来做什么的,RPMs不一定包含的是二进制的内容,不一定需要编译。
- 至少我们需要源码,注意原材料的收集。
- 官方建议使用干净的源码,如果有补丁需要在制作的过程中打上补丁。
- 同一个软件,不同版本的RPM,新版本是否可以支持升级旧版本。需不需要清理旧版本的文件。升级是否会造成冲突。
- 依赖关系。
- 每一个PRM包都提供一种功能,Capability,可以被其他的PRM包依赖。RPM包的名字和所安装的文件都可以给其他的软件提供依赖。
- 自身名字的意义,提供的每一文件也可以被依赖,
- 他的安装和运行需要依赖于其他的RPM包本身或者所具有的文件,叫做依赖关系。
- 两类依赖关系,编译依赖和安装依赖。
- 规划依赖关系,写SPEC文件。
- 制作RPMs。
- 简单测试RPMs。
3. RPMs的规划
- 是否是应用程序,是否需要补丁,是否需要新的功能。
- 是一个程序的库文件
- 是一个系统配置文件集
- 是一个文档文件包
- 是否拆分完整的软件,例如:MySQL-5.5.22.tar.gz,在制作RPM包的时候被拆分为MySQL,mysql-server,mysql-devel,等等。
- 是一个二进制还是源码,当时都有。例如:src.rpm,里面包括了 source.tar.gz 和 spec,需要使用者安装完成之后编译再安装。
4. 制作过程
1. 设计目录结构(set up the directory structure)
制作RPM过程中千万不能用root用户
每个版本对于目录的要求不同,五个不同的目录:
- BUILD:不需要放任何的内容,这个目录是真正工作的目录。用于解压编译源码。
- RPMS:制作完成的RPM包放在这个里面,里面的目录的名字和结构与特定平台架构有关,可以交叉平台编译。
- SOURCES:所有收集的源码都在这个目录里面。
- SPECS:放置SPEC文件,作为制作过程的指导说明。以软件包的名字命名,以.spec结尾。
- SRPMS:放置了SRC(source)格式的RPM包。
红帽提供了默认的制作目录,在/usr/src/redhat.1
[LiarLee/usr/src/redhat ~] tree
2. 放置文件到正确的指定的目录(Place the sources in the right dirctory)。
我们首先需要自己制定自己的制作源码目录,在不使用root用户的前提下进行制作,需要修改系统的宏,来制定新的工作目录。修改工作目录的过程如下:
- 使用命令查看默认的宏:
1
2[LiarLee@localhost ~] rpmbuild --showrc \\ 显示所有的相关宏定义
_build——表示目录; __rm——表示命令 - 使用命令查看默认的配置文件:
1
2
3[LiarLee@localhost ~] rpmbuild --showrc | grep macrofiles \\ 显示配置文件的全局路径和文件名
\\ 权限由小到大,后一个文件的参数覆盖前面所有的定义
\\ 所以我们在家目录下创建隐藏文件.rpmmacros可以直接配置自定义的设置。 - 使用命令查看默认的工作目录定义:
1
2[LiarLee@localhost ~] rpmbuild --showrc | grep _topdir \\ 显示默认的工作目录宏定义
\\ 以相同的模式在.rpmmacros中直接覆盖配置,可以更改工作目录 - 更改topdir的宏,使用rpmbuilder的用户,创建.rpmmacros,添加内容配置宏:
1
2
3
4[LiarLee@localhost ~] vim .rpmmacros \\ Create .rpmmacros file
%_topdir /home/rpmbuilder/rpmbild/
[LiarLee@localhost ~] mkdir -pv rpmbuild/{BUILD,RPMS,SOURCES,SPEC,SRPMS}
[LiarLee@localhost ~] rpmbuild --showrc | grep _topdir \\ Review the Result
3. 创建一个spec文件(Create a spec file that tells the rpmbuild command what to do)。
- spec文件使用软件的名字版本作为文件名;.spec作为扩展名。
- rpm -qi mysql & rpm -qpi mysql,命令查看rpm信息,信息从spec文件中定义,软件包信息说明段落定义。
- spec文件有如下几个段落:
- The introduction section
设置软件包的基本信息1
2
3
4
5
6
7
8
9
10
11
12Summary: \\ 简单描述
Name: \\ 软件名字
Version: \\ 版本号
Release: \\ 发行号
License: \\ 协议
Group: \\ GROUP范围在这个文件中描述 share rpm-*/GROUPS
URL: \\ 从何处获取的站点链接,下载路径
Packager: \\ 制作者<制作者邮箱>
Vendor: \\ 制作者的公司或者本人名字
Source: \\ 源文件地址,一个链接地址
BuildRoot: \\ 制作RPM包的时候的虚拟Root目录
BuildRequires: \\ 制作过程依赖于哪些软件包的名字 - The prep section
解压源码包到BUILD目录的段,cd到需要的目录,设置环境变量。1
2%prep
%setup - The build section
这是源码包安装的make过程.1
2
3
4%build
./configure OR %configure
./make OR %{__make}
make % {?_smp_mflags} \\ 多对称处理器加速编译 - The install section
这里是安装make install过程。系统中有install命令,install方式类似于COPY模式.1
2
3
4%install
%{__rm}
%{__make} install DESTDIR="%{buildroot}"
%find_lang %{name} - The script section
这里是定义执行需要的脚本,用来配置环境。例如:添加Apache用户.
%pre Note:安装前执行
%post Note:安装后执行
%preun Note:卸载前执行
%postun Note:卸载后执行 - The clean section
清理之前所用到的BuildRoot目录的。1
2%clean
%{__rm} - The files section
对安装的软件的程序进行规划,哪些文件安装到那个文件夹,BUILDROOT下的所有文件必须在这个段中存在1
2%files
%config(noreplace) \\ 不替换旧的配置 - The changelog section
记录版本迭代1
2
3* Wed Apr 11 2012 Liarlee.site <Liarlee@site.com> - ReleaseNumber 更改时间
- Comments
- Comments
- The introduction section
4. 开始编译(Build the source and binary RPMs)
- rpmbuild命令说明:
1
2
3
4
5
6
7
8
9rpmbuild -bp \\ 执行到prep section
rpmbuild -bc \\ 执行到build section
rpmbuild -bi \\ 执行到install section
rpmbuild -bs \\ 制作源码格式的制作
rpmbuild -bb \\ 制作二进制格式的rpm包
rpmbuild -ba \\ 执行全部格式,BOTH二进制和源码
rpmbuild -bl \\ BUILDROOT存在但是没有在FILES段中为包含进去的文件的CHECK命令 - 关于安装错误的说明:
在执行过程中如果有报错我们只需要去按照提示修正错误即可,在执行结束之后会在RPMS目录下生成需要的RPM包和RPM-DEBUG包.我们只需要RPM包即可,使用rpm -ivh进行安装测试.1
[LiarLee@localhost ~] rpmbuild -ba SoftwareName.spec \\开始制作的命令
rpm2cpio命令的说明
src-rpm包只是将源码打包成RPM格式,当我们安装src.rpm格式的安装包的时候会把包含的文件,解压到用户默认的工作目录下,所以这种格式的RPM包我们不用安装,直接制作RPM包即可.进行rebuild OR recompile.
1
2[LiarLee ~] rpm2cpio mysql.src.rpm > mysql.cpio
[LiarLee cpio -t ~] rpm2cpio mysql.src.rpm |
两个网站的推荐(搜索SRC-RPM包的站点):
rpmfind.net
rpm.pbone.net
二. 从头开始写新的SPEC files
制作RPM包的核心是写SPEC files,难以掌握的地方
介绍SPEC文件的基本语法和简单用法
1. Spec files overview
SPEC file里面都是指令,告诉RPMBuild命令如何一步一步解压,编译,做成不同的RPM包,依赖关系。 Macro是指的变量
大多数的字段由tag+value组成,tag是标签–Directives,不区分大小写;value是区分大小写的.
1.1 宏的自定义
用户自定义宏 : %define macro_name value
引用方式 : %{macro_name} OR %macro_name
1.2 注释的方式
使用#来进行注释
%–不能在注释中使用,如果必须使用需要双写%%
1 | %prep |
2. Defining package infomation
如何定义SPEC文件内的字段
2.1 软件包的信息
- Name - 软件包名称 - 不能有短横线
- Version - 版本号 - 不能有短横线
- Release - 发行版本号
- Group - /usr/src/doc/rpm-version/GROUPS文件中有详细的描述说明有哪些组可以使用
2.2 制作方信息
- Vendor - 公司或者组织制作的RPM
- URL - 一个主页链接
- Packager - 名字<邮箱地址>
- License - 许可,GPLv2,….etc.
2.3 描述信息
- Summary - 不能超过50个字符,短描述
- %description section - 全面描述,如果字符过多可以提前换行.
2.4 定义依赖关系
- Requires : Capability - 定义软件包的能力,如果未定义显示包名.
- Provides : Capability - 定义对外提供的能力
- BuildRequires : Capability - 可以出现多次,直接写出需要的软件包名
2.5 设定Build目录
- build - 用于解压安装源码
- buildroot : ${_tmppath}/%{name}-%{version}-root
使用$RPM_BUILD_ROOT 或者 %{buildroot}
2.6 命名Source文件
使用Sources字段 和 patch字段,指定源文件和补丁
- Source0: https:// OR 相对路径, https不会下载, 自动本地寻址
- Source1: sourcefiles_name
- Source2: sourcefiles_name
- Patch1: patchfiles_name
- Patch2: patchfiles_name
- Patch3: patchfiles_name
补丁定义后可以直接使用patch命令进行补丁的安装,所以使用patch字段
3. Controlling the build
如何控制编译
1 | %prep \\ 把Source内的解压源码包到BUILD目录,cd到源码目录,配置环境 |
4. Filling the list of files
填充文件列表
5. adding change log entries
添加更新日志
CentOS7打包Nginx过程记录
- useradd rpmbuilder -p rpmbuilder
- yum install -y rpmdevtools rpmbuild
- cd /home/rpmbuilder/
- rpmdev-setuptree
- cd ./rpmbuilder
- tree ./
- mv nginx-1.16.1.tar.gz ./rpmbuild/SOURCES/
- vim ./rpmbuilder/SPECS/nginx.spec
- vim nginx.service
- mv nginx.service /rpmbuild/SOURCES/nginx.service
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92%define nginx_user nginx
%define nginx_group nginx
Name: nginx
Version: 1.16.1
Release: 1%{?dist}
Summary: make rpm for nginx, version 1.16.1
Group: System Environment/Daemons
License: GPLv2
URL: http://liarlee.site
Source0: %{name}-%{version}.tar.gz
Source1: nginx.service
BuildRoot: $_topdir/BUILDROOT
BuildRequires: gcc
BuildRequires: gcc-c++
BuildRequires: openssl
BuildRequires: openssl-devel
BuildRequires: pcre
BuildRequires: pcre-devel
BuildRequires: systemd
Requires: openssl
Requires: openssl-devel
Requires: pcre
Requires: pcre-devel
Requires: systemd
%description
For online Ean portal, make by Hayden Lee, and take some personal option.
%prep
%setup -q
%build
./configure \
true--prefix=/data/web-server/nginx \
--user=%{nginx_user} \
--group=%{nginx_group} \
--with-threads \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_gzip_static_module
make %{?_smp_mflags}
%install
%{__rm} -rf %{buildroot}
make install DESTDIR=%{buildroot}
# install systemd-specific files
%{__mkdir} -p $RPM_BUILD_ROOT%{_unitdir}
%{__install} -m644 %SOURCE1 \
$RPM_BUILD_ROOT%{_unitdir}/nginx.service
%files
%defattr(-,root,root)
/data/web-server/nginx/
%config(noreplace) /data/web-server/nginx/conf/nginx.conf
%config(noreplace) /usr/lib/systemd/system/nginx.service
%attr(0644,root,root) /data/web-server/nginx/conf/nginx.conf
%pre
getent group %{nginx_group} >/dev/null || groupadd -r %{nginx_group}
getent passwd %{nginx_user} >/dev/null || \
useradd -r -g %{nginx_group} -s /sbin/nologin \
-d %{nginx_home} -c "nginx user" %{nginx_user}
exit 0
%post
/usr/bin/systemctl preset nginx.service >/dev/null 2>&1 ||:
/usr/bin/systemctl preset nginx-debug.service >/dev/null 2>&1 ||:
# print site info
cat <<BANNER
----------------------------------------------------------------------
Thanks for using nginx!
Please find the official documentation for nginx here:
* http://nginx.org/en/docs/
Commercial subscriptions for nginx are available on:
* http://nginx.com/products/
----------------------------------------------------------------------
BANNER
%preun
/usr/bin/systemctl --no-reload disable nginx.service >/dev/null 2>&1 ||:
/usr/bin/systemctl stop nginx.service >/dev/null 2>&1 ||:
%postun
/usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||:
%{__rm} -rf /data/web-server/nginx