记录学习笔记、分享资源工具、交流技术思想、提升工作效率

RPM包制作原理详解

运维 xiaomudk 6年前 (2015-05-02) 3302次浏览 0个评论

一、简介

在Centos下制作RPM包是使用rpm-build工具。

1.RPM生成要素:

  • 生成rpm所用的文件列表或者源代码
  • 根据文件列表或者源代码生成rpm规范,也就是spec文件
  • 根据spec文件加工源码/文件的工具rpmbuild

2.制作流程:

  • 把源码包放在正常的位置 (如果有补丁的话也一块放入)
  • 确定依赖关系
  • 编写spec文件,rpmbuild命令根据spec文件来制作合适的rpm包 (这一步是重点)
  • 生成rpm包

3.rpmbuild工作目录介绍

如果你的rpm的版本<=4.4.x,那么rpmbuid工具其默认的工作路径是/usr/src/redhat,这就使得普通用户不能制作rpm包,因为权限的问题,在制作rpm软件包时必须切换到root身份才可以。所以,rpm从4.5.x版本开始,将rpmbuid的默认工作路径移动到用户家目录下的rpmbuild目录里,即$HOME/rpmbuild,并且推荐用户在制作rpm软件包时尽量不要以root身份进行操作。

rpmbuild默认工作路径的确定,通常由在/usr/lib/rpm/macros这个文件里的一个叫做%_topdir的宏变量来定义。如果用户想更改这个目录名,rpm官方并不推荐直接更改这个目录,而是在用户家目录下建立一个名为.rpmmacros的隐藏文件,然后在里面重新定义%_topdir,指向一个新的目录名。这样就可以满足某些“高级”用户的差异化需求了。通常情况下.rpmmacros文件里一般只有一行内容,比如:

%_topdir    $HOME/myrpmbuild

在%_topdir目录下一般需要建立6个目录:

目录名 说明 macros中的宏名
BUILD 编译之前,如解压包后存放的路径 %_builddir
BUILDROOT 安装(make install)后生成的软件临时安装目录 %_buildrootdir
RPMS 最终生成的可安装rpm包的所在目录 %_rpmdir
SOURCES 所有源代码和补丁文件的存放目录 %_sourcedir
SPECS 存放SPEC文件的目录(重要) %_specdir
SRPMS src格式的rpm包位置 %_srcrpmdir

查看当前定义的%_topdir

# rpmbuild --showrc | grep topdir
-14: _builddir  %{_topdir}/BUILD
-14: _buildrootdir      %{_topdir}/BUILDROOT
-14: _rpmdir    %{_topdir}/RPMS
-14: _sourcedir %{_topdir}/SOURCES
-14: _specdir   %{_topdir}/SPECS
-14: _srcrpmdir %{_topdir}/SRPMS
-14: _topdir    %(echo $HOME)/rpmbuild

二、rpmbuild命令的用法:

1.从spec文档建立有以下选项:

-bp  #只执行spec的%pre 段(解开源码包并打补丁,即只做准备)
-bc  #执行spec的%pre和%build 段(准备并编译)
-bi  #执行spec中%pre,%build与%install(准备,编译并安装)
-bl  #检查spec中的%file段(查看文件是否齐全)
-ba  #建立源码与二进制包(常用)
-bb  #只建立二进制包(常用)
-bs  #只建立源码包

2.从tarball包建立,与spec类似

-tp #对应-bp
-tc #对应-bc
-ti #对应-bi
-ta #对应-ba
-tb #对应-bb
-ts #对应-bs

3.从源码包建立

--rebuild  #建立二进制包,通-bb
--recompile  #同-bi

4.rpmbuild的其他参数

--buildroot=DIRECTORY   #确定以root目录建立包
--clean  #完成打包后清除BUILD下的文件目录
--nobuild  #不进行%build的阶段
--nodeps  #不检查建立包时的关联文件
--nodirtokens
--rmsource  #完成打包后清除SOURCES
--rmspec #完成打包后清除SPEC
--short-cricuit
--target=CPU-VENDOR-OS #确定包的最终使用平台

三、spec文件编写

1.spec文档中常用的几个宏(变量)

%{_sysconfdir}:   /etc
%{_sbindir}:     /usr/sbin
%{_bindir}:       /usr/bin
%{_datadir}:      /usr/share
%{_mandir}:       /usr/share/man
%{_libdir}:       /usr/lib64
%{_prefix}:       /usr
%{_localstatedir}:   /usr/var
其实以上参数值都是在/usr/lib/rpm/macros文件中定义的,最好不要修改该文件的值,只需要在家目录定义自己需要的值即可。

2.spec文件组成部分

  • spec的头部 #rpm包的一些信息

  • %description #rpm包的描述

  • %prep #预处理,解压源码,打补丁等操作

  • %build #执行源码包的编译,一般是./configure和make

  • %install #软件安装

  • %clean #编译安装后的清理

  • %files #定义要打包到rpm包的文件

  • %pre #安装或者升级软件前要做的事情,比如停止服务、备份相关文件等都在这里做。

  • %post #安装或者升级完成后要做的事情,比如执行ldconfig重构动态库缓存、启动服务等。

  • %preun #卸载软件前要做的事情,比如停止相关服务、关闭进程等。

  • %postun #卸载软件之后要做的事情,比如删除备份、配置文件等。

  • %changelog #软件的更新记录

3.spec文件具体介绍

– spec的头部

Name: nginx                     #用来定义软件包的名称,后面可以使用%{name}的方式引用,不能包含空格,且必须唯一
Version: 1.2.1                  #软件的实际版本号,具体命令需跟源包一致,后面可以使用%{version}使用,不允许出现连字符'-',会被认为非法字符
Release: 1%{?dist}              #发布序列号,具体命令需跟源包一致,后面可以使用%{release}使用,一般是一个整数,也是rpm包版本信息的一部分
Summary:                        #软件包的内容概要,只能用一句话来概括
License: GPL                    #软件授权方式,通常就是GPL
Source0: %{name}-%{version}.tar.gz  #源代码包,可以带多个用Source1、Source2等源,后面也可以用%{source1}、%{source2}引用
BuildRoot: %_topdir/BUILDROOT   #这个是安装软件的时候使用的“虚拟目录”,
                                #该参数非常重要,因为在生成rpm的过程中,执行make install时就会把软件安装到上述的路径中,在打包的时候,同样依赖“虚拟目录”为“根目录”进行操作。后面可使用$RPM_BUILD_ROOT 方式引用。
URL:   http://nginx.org/        #软件的主页
Vendor:  nginx inc.             #发行商或打包组织的信息,例如RedFlag Co,Ltd
Group: System Environment/Daemons    # 软件分组,建议使用标准分组,具体可以查看/usr/share/doc/rpm-4.*/GROUPS
Patch:                          #补丁源码,可使用Patch1、Patch2等标识多个补丁,使用%patch0或%{patch0}引用
prefix                          #主要用于定义可重新定义安装位置的包,也就是在安装时可以通过--prefix来定义包的安装路径
Requires: pcre                  #该rpm包所依赖的软件包名称,可以用>=或<=表示大于或小于某一特定版本,“>=”号两边需用空格隔开,而不同软件名称也用空格分开
BuildRequires:  gcc,make        #制作过程中用到的软件包
Conflicts:                      #该包与哪些软件包冲突
Provides: webserver             #该包提供了什么,通常是包名或者虚拟包名
Packager:                       #打包者的信息,可以是名字或者邮件地址

– %dscription

#软件的详细说明,描述信息可以有多行,如果提供的描述信息是以空格开始的,则该信息单独显示在一行,如果信息前没有空格,则认为描述信息是一个段落,但最多只能有80个英文字符。

– %prep
预处理,解压源码,打补丁等操作

%setup -q  #源码包解压并放好,源码包必须为name-version.tar.gz格式
  注:可根据你的源码的名字格式,来确认解压后名字的格式,否则可能导致install的时候找不到对应的目录

补充一下

%setup 不加任何选项,仅将软件包打开。
%setup -n newdir 将软件包解压在newdir目录。
%setup -c 解压缩之前先产生目录。
%setup -b num 将第num个source文件解压缩。
%setup -T 不使用default的解压缩操作。
%setup -T -b 0 将第0个源代码文件解压缩。
%setup -q 指不显示输出(quietly)
%setup -c -n newdir 指定目录名称newdir,并在此目录产生rpm套件。
%patch 最简单的补丁方式,自动指定patch level。
%patch 0 使用第0个补丁文件,相当于%patch ?p 0。
%patch -s 不显示打补丁时的信息。
%patch -T 将所有打补丁时产生的输出文件删除。

– %build
#开始构建包

%configure                                #%configure是个宏常量,可以接受额外的参数. 也可以通过./configure 来自定义配置
make %{?_smp_mflags} OPTIMIZE="%{optflags}"  #在BUILD/%{name}-%{version}目录中进行make的工作
宏变量都定义在/usr/lib/rpm/marcros中

– %install
#在BUILD/%{name}-%{version}目录中进行make install的操作。这个很重要,因为如果这里的路径不对的话,则下面%file中寻找文件的时候就会失败。 常见内容有:

rm -rf $RPM_BUILD_ROOT                       # $RPM_BUILD_ROOT 等于 BuildRoot变量。也可以写成%{buildroot}, 不过必须都得用小写
%makeinstall                                 # 或者 make install DESTDIR=$RPM_BUILD_ROOT 
                                             #如果需要额外的启动脚本或者配置文件的,也在这一步完成。

*预定义的文件操作:

%__bzip2        /usr/bin/bzip2
%__cat          /bin/cat
%__chgrp        /bin/chgrp
%__chmod        /bin/chmod
%__chown        /bin/chown
%__cp           /bin/cp
%__cpio         /bin/cpio
%__grep         /bin/grep
%__gzip         /usr/bin/gzip
%__install      /usr/bin/install  #建议用这个替换cp
%__ln_s         ln -s
%__mkdir        /bin/mkdir
%__mkdir_p      /bin/mkdir -p
%__mv           /bin/mv
%__rm           /bin/rm
%__sed          /bin/sed
%__tar          /bin/tar
%__unzip        /usr/bin/unzip

– %clean
#清理临时文件
#通常内容为:

[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"

#注意区分RPM_BUILD_ROOT和RPM_BUILD_DIR:
#RPM_BUILD_ROOT是指开头定义的BuildRoot,而RPM_BUILD_DIR通常就是指BUILD,其中,前面的才是%file需要的。

– %files
#定义那些文件或目录会放入rpm中
#这里会在虚拟根目录下进行,千万不要写绝对路径,而应用宏或变量表示相对路径。如果描述为目录,表示目录中除%exclude外的所有文件。

%deffattr (-,root,root)                 #指定包装文件的属性,分别是(mode,owner,group),-表示默认值,对文本文件是0644,可执行文件是0755
%dir /etc/nginx                         #包含一个空目录/etc/xtollwait
%config(noreplace) /etc/nginx/nginx.conf  #如果配置文件存在: 配置文件未修改,刚不发生改变。如果配置文件有修改,文件修饰符为%config,那就会将旧文件改名为.rpmsave并复制新文件,文件修饰符为%config(noreplace),那就会保持旧文件,新文件安装为.rpmnew。(如果不是重要的配置文件改动,推荐使用%config(noreplace))
%exclude                                #列出不想打包到rpm中的文件
                                        #小心,如果%exclude指定的文件不存在,也会出错的。
                                        #%{buildroot}里的所有文件都要明确被指定是否要被打包到rpm里。什么意思呢?假如,%{buildroot}目录下有4个目录a、b、c和d,在%files里仅指定a和b要打包到rpm里,如果不把c和d用exclude声明是要报错的
%doc  README                            # 当用户安装rpm时,由这个%doc所指定的文件都会安装到/usr/share/doc/name-version/目录里
%attr(0755,root,root) %dir %{_localstatedir}/cache/nginx    #给特定的文件或目录设置权限

– %changelog #变更日志
日志使用 data +"%a %b %d %Y",需要显示包的日志改变的信息可以使用 rpm-q –changelog


本网站采用知识共享署名-相同方式共享 4.0 国际许可协议进行授权
转载请注明原文链接:RPM包制作原理详解
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址