linux下RPM包制作

1.rpmbuild
rpm是Redhat系linux系统的包管理器,使用rpmbuild工具可以制作rpm包。

2.rpmbuild的配置文件
(1)rpmrc配置文件
/usr/lib/rpm/rpmrc
/usr/lib/rpm/redhat/rpmrc
/etc/rpmrc
~/.rpmrc
(2)macro宏配置文件
/usr/lib/rpm/macros
/usr/lib/rpm/redhat/macros
/etc/rpm/macros
~/.rpmmacros

3.使用rpmbuild制作rpm包通用过程
通用过程如下:
(1)计划做什么rpm包,比如软件包或库等
(2)收集源码包
(3)如果需要打补丁,收集补丁文件
(4)确定依赖关系包
(5)开始动手制作RPM包
A)设定好目录结构,我们在这些目录中制作我们的RPM包,我们需要下列目录 :
    BUILD —— 源代码解压后的存放目录,以及后续执行的configure,make,make install命令都是在该目录下执行的
    RPMS —— 制作完成后的RPM包存放目录,里面有与平台相关的子目录
    SOURCES —— 收集的源材料,补丁的存放位置
    SPECS   —— SPEC文件存放目录
    SRMPS   —— 存放生成的SRMPS包的目录
B)把源码包或补丁包放入SOURCES目录中
C)创建spec文件,这是纲领文件,rpmbuild命令根据spec文件来制作rpm包
D)使用rpmbuild命令制作rpm包
(6)测试制作的PRM包
(7)为RPM包签名
备注:rpm制作中,最关键的步骤是编写spec文件。

4.rpm制作举例
以制作tengine的安装包为例来说明:
(1)设置制作rpm包的主目录
在RedHat/Centos下制作rpm包的缺省目录是/usr/src/redhat. 当然我们可以自定义这个主目录,方法如下:
新建~/.rpmmacros文件,增加如下内容:
%_topdir        /home/wahaha
备注:表示制作rpm包的主目录是/home/wahaha,之前所说BUILD|RPMS|SOURCES等目录就是在_topdir代表的目录中。
(2)在主目录中创建rpm打包需要用到的子目录
cd /home/wahaha && mkdir -pv {BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
(3)把收集的源码放到SOURCES下
cp /tmp/tengine-1.4.2.tar.gz /home/wahaha/SOURCES
备注:源文件或补丁文件都要放到SOURCES目录中
(4)在SPECS下建立重要的spec文件
cd /home/wahaha/SPECS && vim tengine.spec
备注:这个步骤非常重要,编写spec文件
(5)用rpmbuild命令制作rpm包,rpmbuild命令会根据spec文件来生成rpm包
 rpmbuild 
-ba 既生成src.rpm又生成二进制rpm
-bs 只生成src的rpm
-bb 只生二进制的rpm
-bp 执行到pre段
-bc 执行到build段
-bi 执行到install段
-bl 检测有文件没包含
(6)测试生成的rpm包是否可以使用
可以通过命令:
rpm -ivh tengine-1.4.2-1.el6.x86_64.rpm  ##测试安装
rpm -e tengine  ##测试卸载
(7)为rpm包签名
使用gpg生成秘钥对,然后使用rpm --addsign为rpm包签名,然后使用rpm --checksig命令即可

5.spec文件的结构
spec文件一般包括如下几个部分:
(1)introduction section
该部分主要定义包的一些基本信息,比如程序名、版本号、发行号以及描述信息等。
(2)prep section
该部分是以宏%prep开始。prep section用来解压源码包到BUILD目录,并cd到解压后的目录。
(3)build section
该部分是以宏%build开始。build section是用来编译程序的,例如执行configure、make等命令。值得注意的是,如果源文件不需要编译,这个部分只写一个%build就可以了,其他的留空,既不用写configure,make等命令了。
(4)install section
该部分是以宏%install开始。install section用来将软件安装到临时目录的,即安装测试。后面rpm打包时会从这个临时安装目录中提取文件的。这个安装的临时目录是我们在introduction section定义的BuildRoot标签来指定的,或者rpmbuild有一个buildroot宏来定义的。
(5)clean section
该部分是以宏%clean开始。主要用来清除BUILD目录中的内容。
(6)files section
该部分是以宏%files开始。用于指定最终生成的rpm包中应该包含哪些文件(在BUILDROOT路径下找),files段中指明的文件一定要在BUILDROOT目录下存在,不然会报错哦
(7)changelog section
该部分是以宏%changelog开始。用来说明该软件的变更历史信息。
备注:以上是spec主要的几个部分,其实在复杂的应用场景中,还有其他的section哦,慢慢了解吧

如下为tengine软件的spec文件举例:
### 0.define section                 #自定义宏段,这个不是必须的
### %define nginx_user nginx         #这是我们自定义了一个宏,名字为nginx_user值为nginx,%{nginx_user}引用

### 1.The introduction section       #介绍区域段
Name:           tengine              #名字为tar包的名字
Version:        1.4.2                #版本号,一定要与tar包的一致哦
Release:        1%{?dist}            #释出号,也就是第几次制作rpm
Summary:        tengine from TaoBao  #软件包简介,最好不要超过50字符
Group:          System Environment/Daemons       #组名,可以通过less /usr/share/doc/rpm-4.8.0/GROUPS选择合适的组
License:        GPLv2                            #许可,GPL还是BSD等 
URL:            http://laoguang.blog.51cto.com   #可以写一个网址
Packager:       Laoguang          #rpm包制作作者
Vendor:         TaoBao.com                       #rpm包所属组织
Source:        %{name}-%{version}.tar.gz         #定义用到的source,也就是你收集的,可以用宏来表示,也可以直接写名字。如果有多个源文件的话,可以通过Source0、Source1、Source2等来指定
patch0:            a.patch                       #rpm包制作需要的补丁,如果有的话,需要写上。如有多个补丁包,可以通过patch0、patch1等来指明
BuildRoot:      %_topdir/BUILDROOT               #这个是软件make install的测试安装目录,也就是测试中的根。我们可以自定义这个目录的位置
BuildRequires:  gcc,make                         #编译阶段需要依赖的包
Requires:       pcre,pcre-devel,openssl,chkconfig  #使用rpm -ivh安装已经制作完成的rpm包时需要依赖的包
%description                                       #软件包描述,尽情的写吧
It is a Nginx from Taobao.                         #描述内容

###  2.The Prep section 准备阶段,主要目的解压source并cd进去
%prep                                  #以%prep宏开始
%setup -q                              #这个宏的作用静默模式解压并cd
%patch0 -p1                            #如果需要在这打补丁,依次写

###  3.The Build Section 编译制作阶段,主要目的就是编译
%build                                 #以%build宏开始
./configure \                          #./configure 也可以用%configure来替换
  --prefix=/usr \                                
  --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.log \
  --pid-path=/var/run/nginx/nginx.pid  \
  --lock-path=/var/lock/nginx.lock \
  --user=nginx \
  --group=nginx \
  --with-http_ssl_module \
  --with-http_flv_module \
  --with-http_stub_status_module \
  --with-http_gzip_static_module \
  --http-client-body-temp-path=/var/tmp/nginx/client/ \
  --http-proxy-temp-path=/var/tmp/nginx/proxy/ \
  --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
  --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
  --http-scgi-temp-path=/var/tmp/nginx/scgi \
  --with-pcre
make %{?_smp_mflags}                   #make后面的意思是,如果就多处理器的话make时并行编译

###  4.Install section  安装阶段
%install                               #以%install宏开始     
rm -rf %{buildroot}                    #先删除原来的安装的,如果你不是第一次安装的话
make install DESTDIR=%{buildroot}      #DESTDIR指定安装的目录,而不是真实的安装目录,所以在introduction section设置的BuildRoot就是在这个地方被引用的

###  4.1 scripts section               #没必要可以不写
%pre                                   #rpm安装前执行的脚本
if [ $1 == 1 ];then                    #$1==1 代表的是第一次安装,2代表是升级,0代表是卸载
        /usr/sbin/useradd -r nginx 2> /dev/null  ##其实这个脚本写的不完整
fi
%post                            #安装后执行的脚本

%preun                           #卸载前执行的脚本
if [ $1 == 0 ];then
        /usr/sbin/userdel -r nginx 2> /dev/null
fi
%postun                          #卸载后执行的脚本

###  5.clean section 清理段,删除buildroot
%clean                           #以%clean宏开始
rm -rf %{buildroot}

###  6.file section 要包含的文件
%files                           #以%files宏开始
%defattr (-,root,root,0755)      #设定默认权限,如果下面没有指定权限,则继承默认
/etc/                            #下面的内容要根据你在%{rootbuild}下生成的来写     
/usr/
/var/

###  7.chagelog section  改变日志段
%changelog                       #以%changelog宏开始
*  Fri Dec 29 2012 laoguang  - 1.0.14-1
- Initial version
备注:关于spec文件编写的一些语法知识点
(1)定义标签语法
TagName: value,    ##例如Name: nginx
标签可以当做宏来引用,即可以使用%{TagName}或%TagName来引用(引用tag名称的时候不区分大小写)
备注:BuildRoot可以通过%{buildroot},也可以通过$RPM_BUILD_ROOT来引用。
(2)自定义宏语法
%define macro_name value
然后可以通过%{macro_name }或%macro_name来引用。
(3)spec文件中注释
spec文件中使用#符号,来表示注释
(4)rpm制作中涉及到的宏
%{?dist}   这是一个宏,?表示有就加上,没有就不加。dist一般是系统的发行版本,比如el5,el6,el7等
%{}是宏,像%{__rm}带两个下划线的也是宏,它代表着linux命令。

6.rpm制作和rpm包安装的过程原理
(1)rpmbuild制作执行过程
rpmbuild制作rpm包是以SPEC文件中的剧本来执行的,如下只是简单地说明下过程:
->将SOURCES目录中源文件,解压到BUILD的目录中。例如BUILD/nginx-1.4/*
->切到BUILD/nginx-1.4/目录执行configure,make等命令
->执行make install将软件安装到BUILDROOT目录中(备注:使用rpmbuild制作包的过程中,会有安装的过程,只是说安装到一个临时的目录中)
->file section字段指定BUILDROOT目录中哪些文件被归档到最终的rpm包中
->打包完成后,就执行clean操作,会删除BUILD目录中内容
(2)rpm -ivh安装rpm包的过程
我们通过rpm -qpl *.rpm可以看到rpm包中的文件是有目录结构的,当我们执行rpm -ivh命令时,就会按照这个目录结构来建立,并将相应的文件install命令到对应的位置。另外rpm -ivh时,还会执行SPEC中的一些script section的命令哦,例如创建用户、增加开机启动等。
(3)rpm -Uvh升级软件的过程
通过rpm -Uvh升级软件时,会用新版本rpm包的文件替换到已经安装的系统文件。当然如果是新增的文件,直接install到对应的目录就好了。
备注:使用rpm -ivh或rpm -Uvh都会更新rpm的数据库了。

7.rpm制作的最佳实践
(1)要使用普通账户制作rpm包,因为在制作rpm包中,会执行spec文件中的一些shell命令,如果命令有问题会带来不确定的后果。
(2)在Redhat/Centos 6中,可能需要在软件安装时,能够配置好initd控制脚本以及logrotate日志切割,那我们可以先制作好这些文件,然后作为Source引入到rpm包就可以了。同样地,在RedHat/Centos 7中,可能需要/lib/systemd/system/*.service配置文件,我们也可以先制作好,然后作为源文件引入到rpm包就好了。
(3)有些软件需要用特定的账户执行,例如apache服务用apache账户来启动。那么我们在可以在脚本段中去定义这些操作就好了。
(4)SRPM包中一般包含了源文件、SPEC文件等内容,我们可以下载一些开源软件的srpm包,做一些修改后再重新制作rpm包。当然我们可以学习SPEC的编写内容哦
(5)使用rpm --showrc 或 rpmbuild --showrc命令,可以显示rpmbuild配置文件中定义的宏,灰常重要,例如通过rpm --showrc | grep _topdir就可以查看rpm制作的主目录。当我们编写spec文件中,就可以通过该命令来查看一些宏的具体含义。
(6)有时我们需要对源文件做成多个rpm包,例如mysql就有mysql-%{version}.rpm、mysql-server-%{version}.rpm等,这个是可以在spec文件中控制的,已达到分拆rpm包的目的。
(7)rpm包搜索网址
http://rpmfind.net
http://rpm.pbone.net/



学习资料参考于:
http://laoguang.blog.51cto.com/6013350/1103628
https://www.ibm.com/developerworks/cn/linux/l-rpm/

你可能感兴趣的:(Linux)