一. 引文:
为实现我们的快速安装,特定服务需求的服务部署需求, 我们选择了通过source编译后定制成rpm,存放至自定义yum仓库,通过yum工具规范化管理及部署服务。目前比较常用的rpm打包方式分别为rpmbuild和fpm(在rpmbuild基础上使用ruby做了封装)。
二. rpmbuild 工具:
1. 工具简述
关于rpmbuild默认工作路径的确定,通常由在/usr/lib/rpm/macros这个文件里的一个叫做%_topdir的宏变量来定义。如果用户想更改这个目录名,rpm官方并不推荐直接更改这个目录,而是在用户家目录下建立一个名为.rpmmacros的隐藏文件(注意前面的点不能少,这是Linux下隐藏文件的常识),然后在里面重新定义%_topdir,指向一个新的目录名。这样就可以满足某些“高级”用户的差异化需求了。通常情况下.rpmmacros文件里一般只有一行内容。另外,可以通过命令临时指定工作路径(--define '_topdir /opt/xiao_nginx')。
rpmbuild的目录结构如下:
BUILD 编译前,如解压后存放的路径
BUILDROOT 编译后存放的路径
RPMS 打包后rpm包存放的路径
SOURCES 用于存放源码、补丁,RPM 会自动从该目录自动寻找
SPECS 存放spec文件
SRPMS 源码rpm存放路径注:一般我们都把源码打包成tar.gz格式然后存放于SOURCES路径下,而在SPECS路径下编写spec文档,通过命令打包后,默认会把打包后的rpm包放在RPMS下,而源码包会被放置在SRPMS下
2 .spec脚本编写
生成rpm除了源码外,最重要的就是懂得编写.spec脚本。rpm建包的原理其实并不复杂,可以理解为按照标准的格式整理一些信息,包括:软件基础信息,以及安装、卸载前后执行的脚本,对源码包解压、打补丁、编译,安装路径和文件等。
实际过程中,最关键的地方,是要清楚虚拟路径的位置,以及宏的定义。
%define 变量定义(如:%define pkg_release 1 , 定义变量pkg_release,value为1)Name: 软件包名称(如:xiao-%{pkg_name})
Version: 软件实际版本号(如: %{pkg_version})
Release: 发布序列号( 如:%{pkg_release}%{?dist} )
Summary: 软件包内容概要 (如: nginx 1.12.1)
Packager: 打包者信心 ( 如: xiaoxiang)Group: 软件分组(如:xiao/service)License: 软件授权方式,(如:GPL(自由软件),BSD,MIT,Pubilc Domain(公共域),Distributable(贡献),commercial(商业),Share(共享),通常都是GPL)URL: 联系地址/主页( 如:http://wiki.xiao.com.cn)
Source0: 源代码包(可以有多个 Source0、Source1。。)Requires: 所依赖软件包 ( libxml2-devel,可用>=,<=标识特定版本,如:libpng-devel >= 1.0.20 zlib)
BuildRoot: 安装或编译时的虚拟目录 ( %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) 重要,在生成rpm的过程中,执行make install时就会把软件安装到上述的路径中,在打包的时候,同样依赖“虚拟目录”为“根目录”进行操作。%description #描述(如:xiao official nginx release(1.12.1) )%prep 预处理脚本(如: %setup -q)
%pre 安装前执行的操作%build 构建包(在BUILD/%{name}-%{version}目录中进行的make工作,如:make %{?_smp_mflags} OPTIMIZE="%{optflags}")%install 软件安装(在BUILD/%{name}-%{version}目录中进行make install的操作。这个很重要,因为如果这里的路径不对的话,则下面%file中寻找文件的时候就会失败。如:%makeinstall )%clean 清理临时文件(如:rm -rf "$RPM_BUILD_ROOT")
%post rpm安装后执行的脚本
%preun rpm卸载前执行的脚本
%postun rpm卸载后执行的脚本%files 定义软件包所包含的文件,分为三类--说明文档(doc),配置文件(config)及执行程序,还可定义文件存取权限,拥有者及组别。
%defattr (-,root,root) 指定包装文件的属性,分别是(mode,owner,group),-表示默认值,对文本文件是0644,可执行文件是0755%changelog 修改日志段。你可以将软件的每次修改记录到这里,保存到发布的软件包中,以便查询之用。每一个修改日志都有这样一种格式:第一行是:* 星期 月 日 年 修改人 电子信箱。其中:星期、月份均用英文形式的前3个字母,用中文会报错。接下来的行写的是修改了什么地方,可写多行。一般以减号开始,便于后续的查阅
%prep:
关于源码结构, 标准的应该为:sourcename-version.tar.gz , 也可以是一个源码目录。%prep时通过-n指定目录即可
%prep%setup -n %{name}
%setup -q 成功执行的前提是你位于SOURCES目录下的源码包必须是name-version.tar.gz的格式
%build:
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make的工作 ,常见写法:
引用make %{?_smp_mflags} OPTIMIZE="%{optflags}",都是一些优化参数,定义在/usr/lib/rpm/marcros中
如:
%build./configure --prefix=%{_prefix} --enable-final
make
%install:
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make install的操作。这个很重要,因为如果这里的路径不对的话,则下面%file中寻找文件的时候就会失败。 常见内容有:
%makeinstall 这不是关键字,而是rpm定义的标准宏命令。也可以使用非标准写法:
引用make DESTDIR=$RPM_BUILD_ROOT install , 或引用make prefix=$RPM_BUILD_ROOT install 。需要说明的是,这里的%install主要就是为了后面的%file服务的。
%install
rm -fr $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
cp -r $RPM_BUILD_ROOT%{_datadir}/apps/kolourpaint/icons/hicolor/* $RPM_BUILD_ROOT%{_datadir}/icons/crystalsvg/
%files:
由于必须在%file中包括所有套件中的文件,所以,我们需要清楚编译完的套件到底包括那些文件?常见的做法是,人工模拟一次编译的过程:
./configrue --prefix=/usr/local/xxx
make
make DESTDIR=/usr/local/xxx install或 make prefix=/usr/local/xxx install
%changelog :
eg:
%changelog
* Sat Jun 23 2015 Karanbir Singh <kbsingh@centos.org> - 13.21.176.1.el6.centos
- Build for CentOS-7.3
三. 案例(自定义nginx rpm包):
tree -L 2 xiao_nginx/
xiao_nginx/
├── BUILD
├── BUILDROOT
├── package.spec
├── RPMS
│ └── x86_64
├── SOURCES #打包目录nginx 及三个依赖模块
│ ├── Luajit
│ ├── lua-nginx-module-0.10.10
│ ├── nginx
│ └── ngx_devel_kit-0.3.0
├── SPECS
└── SRPMS
package.spec,编写:
# cat package.spec
%define pkg_name nginx
%define pkg_version 1.12.1
%define pkg_release 1Name: xiao-%{pkg_name}
Version: %{pkg_version}
Release: %{pkg_release}%{?dist}
Summary: nginx 1.12.1
Packager: xiaoxiangGroup: xiao/service
License: GPL
URL: http://wiki.xiao.com.cn
Source0: nginx
Source1: Luajit
Source2: lua-nginx-module-0.10.10
Source3: ngx_devel_kit-0.3.0Requires: libxml2-devel,libxslt-devel,pcre-devel,openssl-devel,GeoIP-devel,lua-devel
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)%description
xiao official nginx release(1.12.1)%prep%build%install
mkdir -p $RPM_BUILD_ROOT/usr/local/
mkdir -p $RPM_BUILD_ROOT/opt/
cp -a %{SOURCE0} $RPM_BUILD_ROOT/opt/nginx
cp -a %{SOURCE1} $RPM_BUILD_ROOT/usr/local/Luajit
cp -a %{SOURCE2} $RPM_BUILD_ROOT/usr/local/lua-nginx-module-0.10.10
cp -a %{SOURCE3} $RPM_BUILD_ROOT/usr/local/ngx_devel_kit-0.3.0%clean
rm -rf $RPM_BUILD_ROOT%files
/opt/nginx
/usr/local/Luajit
/usr/local/lua-nginx-module-0.10.10
/usr/local/ngx_devel_kit-0.3.0
/ngx_devel_kit-0.3.0
/lua-nginx-module-0.10.10
%changelog
执行打包命令:
#rpmbuild -bb --define '_topdir /opt/xiao_nginx' xiao_nginx/package.spec
#ls xiao_nginx/RPMS/x86_64/
xiao-nginx-1.12.1-1.amzn1.x86_64.rpm