rpm包制作过程

一、'''RPM简介'''


Linux系统上的软件包管理器用于实现对系统上的安装的程序进行跟踪和管理,其中比较著名的有rpm,dpkg等。RPM的全称为RPM Package Manager(早期也叫做Red Hat Package Manager),它最早是Red Hat开发用于实现在Red Hat Linux上软件管理的工具;而目前得益于其强大的管理功能,许多发行版都采用了RPM作为其进行软件包管理的工具,这也使得RPM成为了事实上的工业标准。当然,RPM这个软件本身也由Red Hat基于开源协定发行。最近,RPM文件格式也被LSB(Linux Standards Base)采用为官方标准。

RPM最早主要由Red Hat的Marc Ewing和Erik Troan开发,其在管理软件包方面表现出了以下特性(即其设计目标):


(1)易用性

(2)软件包导向(即以package为中心)

(3)便于升级

(4)跟踪软件包之间的依赖关系

(5)易于查询

(6)支持多种系统架构

(7)使用纯净的源代码(pristine source)


制作好的RPM格式的软件包包含一组带标签的数据(如NAME:nginx)和软件包主体,其通常是一个归档压缩文件,里面包含一个或多个文件,以及用于指明各文件安装位置、属主/属组、权限等信息的安装指令。标签数据用于描述软件包必要可选特征;而软件包主体则主要是指要安装在系统上的文件。进一步来说,RPM包通常包含四个组成部分:用于标示文件格式为RPM格式的前导标示区、数字签名、标签数据(也叫首部)和主体。


为了便于软件包的管理,所有的rpm包的命令格式均遵循统一的规范,其共有四个部分组成:name-version-release.architecture.rpm。


RPM分为两种类型:二进制格式和源码。二进制格式的RPM包已经编译好且可安装于特定平台,里面通常包含编译好的程序、库文件、配置或帮助文件等。当然,也有一些二进制格式的RPM包是平台无关的,即其名称中平台部分为noarch的RPM包。而源码格式的RPM包通常是打包起来的可用于制作二进制格式RPM包的命令、脚本、程序源码和程序补丁等,其可用于在特定平台上进行快速制作生成二进制格式的RPM包。

在系统上,RPM数据库用于存储安装至当前系统的所有RPM包的相关信息,其通常是位于/var/lib/rpm/目录中的众多文件。这些文件可用于已安装RPM包的查询、校验等功能,其通常为:


[[文件:Example.jpg]]


其中,__db.001类的文件是RPM用于软件包管理时的锁文件,余下的其它文件通常为Berkeley DB格式的文件,其中最重要的是Packages,其包含了当前系统已经安装的所有RPM包的首部标签信息。其它文件如Name,Providename和Group等通常是为提高访问效率的,一旦损坏,它们都可以使用rpm命令的--rebuild进行重建。



二、'''制作过程'''


可以分为如下几个步骤:


(1)确定要生成的RPM包,包括打包的所有内容和制作完成后要生成RPM包的类型;

(2)收集打包用到的相关源程序、相关文件及补丁文件;

(3)如要打包的是一个应用程序,还需要事先阅读其README、INSTALL等相关文件,并测试出其符合制作需要并可正常完成编译安装过程;

(4)如果此RPM包可能用于升级老版本程序,还需要规划其升级相关事项,比如,如何处理老版本程序的配置文件,是不是要执行一些处理脚本等;

(5)确定此RPM包的依赖关系,包括制作时依赖的“能力”及安装时依赖的“能力”等;

(6)制作生成RPM包;


而具体制作生成RPM包的过程,简单来说,就是为制作过程提供一个“工作车间”,即一个目录,里面需要包含以下几个子目录:


 BUILD   ―― 编译相关源码包时的工作目录;

 RPMS    ―― 生成的二进制格式的RPM包存放的位置;

 SOURCES ―― 程序的源码文件及其它辅助文件的存放位置;

 SPCES   ―― spec文件的存放位置;

 SRPMS   ―― 生成的src格式的RPM包存放的位置;


当“工作车间”准备停当之后,将用到的源码及辅助文件放置于相应的SOURCES目录中,并在SPECS目录中创建一个spec文件,就可以使用rpmbuild命令开始制作过程了。由于root用户的权限没有任何限制,RPM制作过程的不当命令有可能会给系统带去破坏,所以,一定不能使用root用户执行制作过程。切记!


通常,specs文件与制作的RPM包同名,且以.specs结尾以方便识别。再次说明,用于打包的放置于%{_topdir}/SOURCES目录中的文件既可能是某程序归档格式的源码包,如nginx-1.2.1.tar.gz,也可以是纯粹的一些文件。只不过,如果包含源码,为了制作生成二进制格式的RPM包,打包的过程需要将此源程序先解压编译(在BUILD目录中完成编译)后进行打包,否则,就省去了编译这道程序而可以直接进行打包。


将以nginx-1.2.1.tar.gz制作为RPM包的最简单方法为例,我们只需要将nginx-1.2.1.tar.gz放置于%{_topdir}/SOURCES目录中,并为其在%{_topdir}/SPECS目录中创建一个名为nginx.spec的文件,并在此文件中设定好制作nginx这个RPM包的各相关指令即可。事实上,制作spec文件的过程是相当复杂的,但其也是制作RPM包过程中最关键的步骤。



下面是一个框架性的spec文件,几乎所有的spec文件都可以基于此框架扩展而来。


[[文件:spec.jpg]]


上面的这个框架大致可以分为八个部分:

(1)%description前面的所有内容都是以“tag: value”的格式定义,包括%description这些均为rpm包相关信息的描述段。其中许多信息即为使用“rpm -qi”对其查询时所显示的内容。许多标签可以做到见其名知其义,如Name用于定义RPM包的名字、License用于说明其许可证信息、Summary用于为此rpm包定义一个简单描述等。而%description则用于定义一个此rpm包的比Summary标签中更详细些描述信息。

(2)%prep部分为制作rpm过程的准备阶段(prepare section)。如果是对某归档格式的源程序制作rpm包,此段中经常要使用%setup来实现将源码解压至%{_topdir}/BUILD目录中,并使用cd命令将制作过程的工作目录切换至此解压后的源码目录。当然,%setup也有一些选项实现更进一步的设置。

(3)%build部分为编译阶段(build section)。如果制作rpm包的源材料不是源程序,此段可以不用设置;如果是C/C++等类的程序,此处对应于其编译安装过程中的“configure”和“make”两步;如果是perl类的源程序,此处通常对应于其编译安装过程中的“perl Makefile.PL”和“make”两步。然而,为了编译过程中的编译环境设定不出现问题,此处如果要用到configure脚本时通常要使用宏%configure来替换。可以使用“rpm --eval '%configure'”命令来获取当前系统上%configure宏的相关定义。

(4)%install部分为安装阶段。制作rpm时,所有要打包进rpm包的文件都需要事先按照其计划最终安装在系统上的路径先安装至一个临时目录中,此临时目录做为模拟的系统根目录,其通常称为BUILDROOT目录。此目录可以在spec文件中使用“BuildRoot:”标签进行定义。 因此,可以在后文中使用%{BuildRoot}引用,事实上其也可以使用$RPM_BUILD_ROOT引用。

(5)%clean部分为清理阶段。此段通常用于清理其它阶段的命令所创建的文件,比如“rm -rf $RPM_BUILD_ROOT”命令即为删除前次制作rpm包时安装生的BUILDROOT目录。

(6)%pre、%post、%preun和%postun为脚本段。%pre为制作完成后的rpm在其安装之前要执行的脚本,%post为安装完成后执行的脚本,%preun为卸载开始之前执行的脚本,%postun为卸载完成后要执行的脚本。

(7)%files部分为文件列表段。此段中需要列出打包进rpm包的所有文件,同时还需要为这些文件定义安装到系统上之后的权限。

(8)%changlog部分为改变日志段。此段中用于定义当前spec文件每一次改进的作者及改进的相关说明信息。


三、'''案例'''


其过程为,首先将nginx-1.2.1.tar.gz源码包及需要的源码包放入%{_topdir}/SOURCES目录,这里为/home/wsg/rpmbuild//SOURCES目录,创建%{_topdir}/SPECS下的nginx.spec文件内容为:


%define _prefix         /usr/local/services/nginx

%define _user           www

%define _user_uid       501

%define _group          www

%define _group_gid      501

%define _sbin_path      /usr/sbin

%define name    nginx

%define version 1.2.1

%define release 1

%define license GPL

%define group  System Environment/Daemons

%define source nginx-%{version}.tar.gz

%define url http://www.nginx.org

Name:           %{name}

Version:        %{version}

Release:        %{release}

License:        %{license}

Summary:        %{summary}

Group:          %{group}

Source:         %{source}

URL:            %{url}

Prefix:         %{_prefix}

Buildroot:      %{buildroot}

BuildRequires:  pcre-devel,zlib-devel,openssl-devel,libxml2-devel,libxslt-devel,gd-devel

Requires:       pcre,zlib,openssl,libxml2,libxslt,gd

%description

Nginx is a free, open-source, high-performance HTTP server and reverse proxy,

as well as an IMAP/POP3 proxy server. Igor Sysoev started development of Nginx

in 2002, with the first public release in 2004. Nginx now hosts nearly 12.18%

(22.2M) of active sites across all domains. Nginx is known for its high

performance, stability, rich feature set, simple configuration, and low

resource consumption.

%prep

%setup -q

%build

export DESTDIR=%{buildroot}

./configure  --prefix=%{_prefix} --user=www --group=www \

--with-http_stub_status_module --with-http_ssl_module \

--with-pcre=/home/wsg/rpmbuild/SOURCES/pcre-8.30 --with-http_realip_module \

--with-http_gzip_static_module --with-http_sub_module \

--add-module=/home/wsg/rpmbuild/SOURCES/ngx_cache_purge-1.5

make %{?_smp_mflags}

%install

rm -rf %{buildroot}

make install DESTDIR=%{buildroot}

mkdir -p %{buildroot}/%{_initrddir}

(

cat <<'EOF'

#!/bin/bash

# nginx Startup script for the nginx HTTP Server

# this script create it by Luo Hui at 2008.11.11.

# if you find any errors on this scripts,please contact Luo Hui.

# and send mail to farmer.luo at gmail dot com.

#

# chkconfig: - 85 15

# description: nginx is a high-performance web and proxy server.

# processname: nginx

# nginx pidfile: /var/run/nginx.pid

# nginx config: /usr/local/nginx/conf/nginx.conf

nginxd=%{_prefix}/sbin/nginx

nginx_config=%{_prefix}/conf/nginx.conf

nginx_pid=/var/run/nginx.pid

RETVAL=0

prog="nginx"

# Source function library.

. /etc/rc.d/init.d/functions

# Source networking configuration.

. /etc/sysconfig/network

# Check that networking is up.

[ ${NETWORKING} = "no" ] && exit 0

[ -x $nginxd ] || exit 0

ulimit -HSn 65535

# Start nginx daemons functions.

nginx_start() {

       if [ -e $nginx_pid ];then

               echo "nginx already running...."

               exit 1

       fi

       if [ ! -d %{_prefix}/logs ];then

               mkdir -p %{_prefix}/logs

       fi

       if [ ! -d %{_prefix}/tmp ]; then

               mkdir -p %{_prefix}/tmp

       fi

       if [ -e $nginx_pid ];then

               echo "nginx already running...."

               exit 1

       fi

       echo -n $"Starting $prog: "

       daemon $nginxd -c ${nginx_config}

       RETVAL=$?

       echo

       [ $RETVAL = 0 ] && touch /var/lock/subsys/nginx

       return $RETVAL

}

# Stop nginx daemons functions.

nginx_stop() {

       echo -n $"Stopping $prog: "

       killproc $nginxd

       RETVAL=$?

       echo

       [ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx $nginx_pid

}

# reload nginx service functions.

nginx_reload() {

       echo -n $"Reloading $prog: "

       #kill -HUP `cat ${nginx_pid}`

       killproc $nginxd -HUP

       RETVAL=$?

       echo

}

# See how we were called.

case "$1" in

start)

       nginx_start

       ;;

stop)

       nginx_stop

       ;;

reload)

       nginx_reload

       ;;

restart)

       nginx_stop

       nginx_start

       ;;

status)

       status $prog

       RETVAL=$?

       ;;

*)

       echo $"Usage: nginx {start|stop|restart|reload|status|help}"

       exit 1

esac

exit $RETVAL

EOF

) >%{buildroot}/%{_initrddir}/nginx

chmod 755 %{buildroot}/%{_initrddir}/nginx

%clean

rm -rf %{buildroot}

%files

%defattr(-,root,root)

%dir %{_prefix}/

%attr(0755,%{_user},%{_group}) %dir %{_prefix}/logs

%dir %{_prefix}/sbin

%dir %{_prefix}/conf

%dir %{_prefix}/html

%{_prefix}/sbin/nginx

%{_prefix}/conf/fastcgi.conf

%{_prefix}/conf/fastcgi_params.default

%{_prefix}/conf/win-utf

%{_prefix}/conf/koi-utf

%{_prefix}/conf/nginx.conf.default

%{_prefix}/conf/fastcgi.conf.default

%{_prefix}/conf/fastcgi_params

%{_prefix}/conf/koi-win

%{_prefix}/conf/mime.types

%{_prefix}/conf/nginx.conf

%{_prefix}/conf/mime.types.default

%{_prefix}/conf/scgi_params

%{_prefix}/conf/scgi_params.default

%{_prefix}/conf/uwsgi_params

%{_prefix}/conf/uwsgi_params.default

%{_prefix}/html/50x.html

%{_prefix}/html/index.html

%{_initrddir}/nginx

%changelog

* Fri Jun 07 2013

- init


为了保证接下来的制作过程能够顺利进行,此时可以使用rpmbuild命令的--nobuild选项测试spec文件所依赖的环境是否已经完全准备好。例如

[wsg@minion SPECS]$ rpmbuild --nobuild nginx.spec

error: Failed build dependencies:

pcre-devel is needed by nginx-1.2.1-1.x86_64

gd-devel is needed by nginx-1.2.1-1.x86_64


上述命令的执行结果即显示制作过程的依赖的两个rpm包尚未安装,其结果就是制作过程根本不能启动。因此,这里需要事先解决依赖关系。当测试没有任何信息提示后就可以开始下一节的步骤了。


1.命令简介


制作rpm包使用rpmbuild命令进行,其语法格式为:


rpmbuild  -bBuildStage  spec_file

其中,-b选项用于告诉rpmbuild命令开始制作一个RPM包,而BuildStage选项通常也为一个字符,其用于控制rpmbuild命令在基于指定的spec文件制作rpm包时进行到哪个步    骤。其常用方式有:

-ba  同时制作成生二进制格式的rpm包和源码格式的rpm包;

-bb  仅制作二进制格式的rpm包;

-bc  仅执行到spec文件中的%build阶段即停止进行;

-bp  仅执行至spec文件中的%prep阶段即停止进行;

-bi  仅运行至spec文件中的%install阶段即停止运行;

-bl  检查spec文件中%file段所列出的文件是不是与BUILDROOT目录中存在的文件完全匹配;

-bs  仅制作生成源码格式的rpm包;

然后运行:'''rpmbuild -bb nginx.spec''' 就可以成功生成rpm包了。


三、'''参考资料'''


http://hlee.javaeye.com/blog/343499 ''RPM包rpmbuild SPEC文件深度说明''


你可能感兴趣的:(rpm包制作)