制作RPM包规范和rpm相关命令



RPM命令和RPM制作

1.  RPM是什么

RPM全名是“RedHat Package Manager,简称则为RPM,顾名思义,当初这个软件管理工具是由RedHat这家公司发展出来的。RPM是以一种数据库记录的方式来将你所需要的软件安装到你的Linux系统的一套管理机制。

RPM最大的特点就是将你要安装的软件先编译过,并且打包成为RPM机制的安装包,通过包装好的软件里头默认的数据库记录这个软件的要安装的时候必须具备的依赖性软件,当安装在你的Linux主机时,RPM会先依照软件里头的数据查询Linux主机的依赖属性软件是否满足,若满足则予以安装,若不满足则不安装。安装的时候同时会将该软件的信息整个写入RPM的数据库中,以便未来的查询、验证和反安装。

1.1 RPM的类型

1.1.1   RPM

RPM包是由供应商释出的二进制包,这种形式的RPM包,与windows平台的可执行文件类似,安装起来速度也很快。并且我们也可以通过RPM命令去查看该二进制包的描述信息。因为RPM包是经过编译的源码包,所以我们无法通过这种类型的包去检索源码,也无法通过手动挑选编译选项自定义功能。但这种方式简单,方便的优点使得RPM包使用的非常广泛。

1.1.2   SRC RPM

src.rpm这种类型的包,在实际工作中,有些厂商在制作RPM的同时,会同时释出同等版本的srcrpm包。这种类型的包的内容,是尚未编译的源码包,补丁文件,SPEC文件,取得这类文件之后,同样适用rpm -ivh 的方式安装,此时会把spec文件和源码包及补丁文件分别放置在rpmbuild的相应目录结构下,之后需要再次编译源码包生成可执行的rpm包,进行安装升级即可。因而在编译之前,我们可以在spec文件中指定编译的选项定制生成的rpm的功能。同时,如果要在飞腾平台上制作没有的RPM包,比如说要制作openssl-1.0.2,在找到openssl-1.0.2.tar.gz源码包之后,可以在rpmfind网站,找到对应的x86_64RPM包,查找其相应的src.rpm,根据现有的spec文件,编写自定义的spec文件。进而编译出以前并不存在的RPM包。使用rpm这种软件管理机制管理RPM包。

 

1.2 Linux软件安装的两种形式

1.2     

1.2.1   源码安装

其实,在linux下面安装一个源码包是最常用的,笔者在日常的管理工作中,大部分软件都是通过源码安装的。安装一个源码包,是需要我们自己把源代码编译成二进制的可执行文件。如果你读得懂这些源代码,那么你就可以去修改这些源代码自定义功能,然后再去编译成你想要的。使用源码包的好处除了可以自定义修改源代码外还可以定制相关的功能,因为源码包在编译的时候是可以附加额外的选项的。

1.1.1.1. c语言源码安装过程

源码包的编译用到了linux系统里的编译器,常见的源码包一般都是用C语言开发的,这也是因为C语言为linux上最标准的程序语言。Linux上的C语言编译器叫做gcc,利用它就可以把C语言变成可执行的二进制文件。所以如果你的机器上没有安装gcc就没有办法去编译源码。可以使用yum -y groupinstall “Development Tools”安装开发环境。

安装一个源码包,通常需要三个步骤:

1. /configure 在这一步可以定制功能,加上相应的选项即可,具有有什么选项可以通过”./config --help ”命令来查看。可以通过在这个步骤指定安装路径,如./configure--prefix=/usr/local/xxx,之后make install时会把软件安装到/usr/local/xxx目录下,这样,在我们想要卸载软件时,只需要删除目录/usr/local/xxx即可。在在这一步会自动检测你的linux系统与相关的套件是否有编译该源码包时需要的库,因为一旦缺少某个库就不能完成编译。只有检测通过后才会生成一个Makefile文件。

2. make 使用这个命令会根据Makefile文件中预设的参数进行编译,这一步其实就是gcc在工作了。这一步骤通常是最为耗时的动作。

3. make install 安装步骤,生成相关的软件存放目录和配置文件的过程。

上面介绍的3步并不是所有的源码包软件都一样的,笔者以前也曾经遇到过,安装步骤并不是这样,也就是说源码包的安装并非具有一定的标准安装步骤。这就需要你拿到源码包解压后,然后进入到目录找相关的帮助文档,通常会以INSTALL或者README为文件名。所以,你一定要去看一下。

1.1.1.2. Python 源码包安装

Python第三方库几乎都可以在github或者 pypi上找到源码。源码包格式大概有zip tar.zip tar.bz2。解压这些包,进入解压好的文件夹,通常会有一个setup.py的文件。打开命令行,进入该文件夹。运行以下命令,就能把这个第三库安装到系统里:

pythonsetup.py install

同样在这种含有setup.py的源码包中,我们可以指定参数进行软件功能的定制。可以通过执行python setup.py –help可以看到可以为setup.py函数指定参数,常见的参数含义如下:

>>python setup.py --help
  --name              
包名称

  --version (-V)      
包版本
  --author            
程序的作者
  --author_email      
程序的作者的邮箱地址
  --maintainer        
维护者
  --maintainer_email  
维护者的邮箱地址
  --url              
程序的官网地址
  --license          
程序的授权信息
  --description      
程序的简单描述
  --long_description  
程序的详细描述
  --platforms        
程序适用的软件平台列表
  --classifiers      
程序的所属分类列表
  --keywords          
程序的关键字列表
  --packages  
需要打包的目录列表
  --py_modules  
需要打包的python文件列表
  --download_url  
程序的下载地址
  --cmdclass  
  --data_files  
打包时需要打包的数据文件,如图片,配置文件等
  --scripts  
安装时需要执行的脚步列表

可以通过—help-commands列出可以帮助的命令参数,尤其要注意的是bdist_rpm这个命令,可以把这种形式的源码包直接制作成rpm包,很好的命令。

[[email protected]]# python setup.py --help-commands

Standardcommands:

  build             build everything needed to install

  build_py          "build" pure Python modules(copy to build directory)

  build_ext         build C/C++ extensions (compile/linkto build directory)

  build_clib        build C/C++ libraries used by Pythonextensions

  build_scripts     "build" scripts (copy and fixup#! line)

  clean             clean up temporary files from'build' command

  install           install everything from builddirectory

  install_lib       install all Python modules (extensionsand pure Python)

  install_headers   install C/C++ header files

  install_scripts   install scripts (Python or otherwise)

  install_data      install data files

  sdist             create a source distribution(tarball, zip file, etc.)

  register         register the distributionwith the Python package index

  bdist             create a built (binary)distribution

  bdist_dumb        create a "dumb" builtdistribution

  bdist_rpm         create an RPM distribution

  bdist_wininst     create an executable installer for MSWindows

  upload            upload binary package to PyPI

  check             perform some checks on the package

 

Extracommands:

  rotate            delete older distributions, keepingN newest files

  develop           install package in 'developmentmode'

  setopt            set an option in setup.cfg oranother config file

  saveopts          save supplied options to setup.cfg orother config file

  egg_info          create a distribution's .egg-infodirectory

  upload_docs       Upload documentation to PyPI

  alias             define a shortcut to invoke one ormore commands

  easy_install      Find/get/install Python packages

  bdist_egg         create an "egg" distribution

  install_egg_info  Install an .egg-info directory for thepackage

  test              run unit tests after in-placebuild

1.2.2   RPM安装

RPM安装,就是很常见的软件包安装的方式了,类似rpm-ivh 以及yum -y install实际执行的都是rpm包安装的过程。但rpm安装的过程中有一个非常关键的难点是依赖性问题。即安装软件包A,需要先安装软件包B,而安装软件包B,又需要先安装软件C,这种依赖形式为线性依赖,需要在安装时,先安装C,再装B,再装A。另外有一种依赖形式则成为环形依赖,即仍以上面的例子为例,安装软件C时,需要先安装A,就形成了死循环。其实解决办法很简单,只需在安装的时候将两个rpm包名都附上,例如rpm  -ivh  A、B、C。

rpm包依赖性

树形依赖: a->b->c

环形依赖:a->b->c->a

模块依赖:查询网站:www.rpmfind.net

一般服务器安装都是最小化安装,这样是为了降低被攻击的可能性,由于服务器的最下话安装,导致安装一个软件需要很多依赖,比如树形依赖,在安装依赖a的时候可能需要安装依赖包geyju等,安装b依赖时又需要其他各种依赖,树形依赖虽然麻烦,可以依旧可以解决。环形依赖也不是很难解决,只需要用一条命令abc同时安装就能解决依赖问题。还有一种依赖时模块依赖,它依赖的是某个软件中的程序,我们可以通过查询www.rpmfind.net来安装依赖。

 

  RPM包管理包括rpm命令管理yum在线管理rpm命令管理如上所说,遇到各种依赖问题的时候需要我们自己动手查找依赖包,然后手动解决依赖问题,进行后装。后来人们发现有没有一种什么简单的方法进行安装软件,于是就有了yum命令,事先准备一个包含所有rpm包的网站,作为在线服务器源我们只要使用在线命令安装软件,不管我去依赖那一个包,yum都会自动到服务器上把依赖下载安装。

 

为了解决这种具有相关性的软件之间的问题,所谓的软件依赖属性,RPM就在提供打包的软件时,同时加入一些信息记录的功能,这些信息包括软件的版本、打包软件者、依赖属性的其他软件、本软件的其他功能说明、本软件的所有文件记录等,这些信息均包含在制作rpm包的spec文件中,然后再Linux系统上面建立一个RPM软件数据库。但rpm在安装时,只能能一个一个的去解决依赖,费时费力,所以出现了yum这种解决软件依赖的神器出现了。

1.2.3   RPM的优点

  1. RPM内含已经编译过的程序与设置文件等数据,可以让用户免除重新编译的困扰。

  2. RPM在被安装之前,会先检查系统的硬盘容量、操作系统版本、可避免文件被错误安装。

  3. RPM文件本身提供软件版本信息,依赖属性软件名称】软件用途说明、软件所包含文件等信息,便于了解软件。

  4. RPM管理的方式使用数据库记录RPM文件相关的参数,便于升级、删除、查询与验证。

2.1   

2.  RPM能做什么

RPM RPM Package Manager 的简写,是发源于 Red-hat 系统的软件管理工具,所以最初的名字叫做 Red-hat PackagerManager。目前,RPM 已发展成为业界认可的 Linux 系统软件管理工具,适用于各种基于 Linux 内核的系统,如 SUSEFedoraPower 等。RPM 制作灵活且方便使用,能够有效地管理软件包的安装、卸载和升级。

RPM 自身维护了一个数据库(RPM Database),用于记录所有通过 RPM 安装的软件包及其文件信息。RPM Database 提供多种形式的查询功能,同时也提供软件包和相关文件的验证功能。

RPM is a powerful Package Manager, which can beused to build, install, query, verify, update, anderase individual software packages. A package consists of an archive of files and meta-data used to installand erase the archive files.  Themeta-data includes helper scripts[辅助脚本], fileattributes【文件属性】, and descriptive information【描述信息】 about the package.  Packagescome in two varieties: binary packages【二进制包】, used toencapsulate software to be installed, and source packages【源码包】, containing the source  codeand recipe necessary to produce binary packages【源码包包含构建二进制包所需要的源代码和材料】.

 One of thefollowing basic modes must be selected: Query, Verify, Install/Upgrade/Freshen,Uninstall, Set Owners/Groups, Show Querytags, and Show Configuration.

3.  RPM常用命令

3.1  查询信息

rpm 查询rpm包的信息的命令格式为

rpm {-q|--query} [select-options] [query-options]

其中[select-options]的取值如下所列:

[PACKAGE_NAME] [-a,--all] [-f,--file FILE]

[-g,--group GROUP] {-p,--package PACKAGE_FILE]

[--hdrid SHA1] [--pkgid MD5] [--tid TID]

[--querybynumber HDRNUM] [--triggeredbyPACKAGE_NAME]

[--whatprovides CAPABILITY] [--whatrequiresCAPABILITY]

[query-options]

[--changelog] [-c,--configfiles] [--conflicts]

[-d,--docfiles] [--dump] [--filesbypkg][-i,--info]

[--last] [-l,--list] [--obsoletes] [--provides]

[--qf,--queryformat QUERYFMT] [-R,--requires]

[--scripts] [-s,--state][--triggers,--triggerscripts]

其中-f 指定某个文件,查询该文件是由那个rpm包提供的,

[root@localhost ~]# rpm -qf /etc/yum.repos.d/

yum-3.4.3-154.el7.centos.noarch

从上面的代码片段中,我们可以看到/etc/yum.repos.d/目录是由yum这个rpm包提供的。那么yum这个命令是由那个rpm包提供的可以通过下面的方式查询。

 [root@localhost ~]# rpm -q --whatprovides yum

yum-3.4.3-154.el7.centos.noarch

    通过上面的示例,我们可以通过这种方式命令和rpm包的映射,当然也可以通过下面的途径:rpm -qf –FILE

[root@localhost ~]# whereis vim[查询vim可执行路径]

vim: /usr/bin/vim /usr/share/vim /usr/share/man/man1/vim.1.gz

[root@localhost ~]# rpm -qf /usr/bin/vim

vim-enhanced-7.4.160-2.el7.x86_64

[root@localhost ~]# rpm -qf /usr/share/vim

vim-common-7.4.160-2.el7.x86_64

[root@localhost ~]# rpm -q --file /usr/bin/vim

vim-enhanced-7.4.160-2.el7.x86_64

查询rpm中所包含的changelog

[root@localhost ~]# rpm -q --changelog coreutils>> cp

[root@localhost ~]# vim cp

* Fri Jul 01 2016 Ondrej Vasik - 8.22-18

- fix xfs build failure in chrooted environment(#1263341)

- update filesystem lists for stat and tail fromlatest upstream

  (#1327881,#1280357)

 

3.1     

3.1.1   查询系统中所安装的包

使用rpm -qa命令可以列出系统中安装的所有包,之后,则可以通过管道命令grep查询指定名称的rpm包是否存在。

# rpm -qa

gnome-classic-session-3.22.2-10.el7.noarch

jasper-libs-1.900.1-31.el7.x86_64

libsss_autofs-1.15.2-50.el7.x86_64

gettext-libs-0.19.8.1-2.el7.x86_64

……

libini_config-1.3.0-27.el7.x86_64

ibus-libpinyin-1.6.91-4.el7.x86_64

rest-0.8.0-1.el7.x86_64

 

[root@localhost ~]# rpm -qa | grep vim

vim-enhanced-7.4.160-2.el7.x86_64

vim-filesystem-7.4.160-2.el7.x86_64

vim-minimal-7.4.160-2.el7.x86_64

vim-common-7.4.160-2.el7.x86_64

结合通配符

[root@server01 ~]# rpm -qa "mysql*"

mysql-server-5.1.73-5.el6_6.x86_64

mysql-5.1.73-5.el6_6.x86_64

mysql-devel-5.1.73-5.el6_6.x86_64

mysql-libs-5.1.73-5.el6_6.x86_64

结合管道命令,查询最近安装的rpm

[root@localhost rpm]# rpm -qa --last | head

libevent-devel-2.0.21-4.el7.x86_64            Tue 06 Feb 2018 12:58:46 AM EST

wxPython-2.8.12.0-9.el7.x86_64                Sat 03 Feb 2018 09:35:11 AM EST

wxGTK-media-2.8.12-20.el7.x86_64              Sat 03 Feb 2018 09:34:54 AM EST

wxGTK-gl-2.8.12-20.el7.x86_64                 Sat 03 Feb 2018 09:34:53 AMEST

wxGTK-2.8.12-20.el7.x86_64                    Sat 03 Feb 2018 09:34:52 AMEST

wxBase-2.8.12-20.el7.x86_64                   Sat 03 Feb 2018 09:34:49 AMEST

SDL-1.2.15-14.el7.x86_64                      Sat 03 Feb 2018 09:34:49AM EST

mesa-libGLU-9.0.0-4.el7.x86_64                Sat 03 Feb 2018 09:34:49 AM EST

ceph-common-10.2.10-0.el7.x86_64              Thu 01 Feb 2018 08:39:24 PM EST

libbabeltrace-1.2.4-3.el7.x86_64              Thu 01 Feb 2018 08:39:08 PM EST

查询特定 RPM 包是否已安装

命令格式:rpm -q package_name

如果是已安装的包,则返回详细包名;否则,返回此包未安装的提示。比如:

查询某 RPM 包是否已安装

[root@server01 ~]# rpm -q mysql-server

mysql-server-5.1.73-5.el6_6.x86_64

 [root@nimbus-bvt-osee-kilo-rh7~]# rpm -q docker-engine

package docker-engine is not installed

查询特定 RPM 包安装文件的状态

命令格式:rpm -qspackage_name

清单 10. 查询已安装软件包文件状态

 

[root@server01 ~]# rpm -qs pytz

normal        /usr/lib/python2.6/site-packages/pytz

missing       /usr/lib/python2.6/site-packages/pytz-2010h-py2.6.egg-info

normal        /usr/lib/python2.6/site-packages/pytz/__init__.py

normal        /usr/lib/python2.6/site-packages/pytz/__init__.pyc

normal        /usr/lib/python2.6/site-packages/pytz/__init__.pyo

normal        /usr/lib/python2.6/site-packages/pytz/reference.py

normal        /usr/lib/python2.6/site-packages/pytz/reference.pyc

normal        /usr/lib/python2.6/site-packages/pytz/reference.pyo

normal        /usr/lib/python2.6/site-packages/pytz/tzfile.py

normal        /usr/lib/python2.6/site-packages/pytz/tzfile.pyc

normal        /usr/lib/python2.6/site-packages/pytz/tzfile.pyo

normal        /usr/lib/python2.6/site-packages/pytz/tzinfo.py

normal        /usr/lib/python2.6/site-packages/pytz/tzinfo.pyc

normal        /usr/lib/python2.6/site-packages/pytz/tzinfo.pyo

normal        /usr/share/doc/pytz-2010h

normal        /usr/share/doc/pytz-2010h/CHANGES.txt

normal        /usr/share/doc/pytz-2010h/LICENSE.txt

normal        /usr/share/doc/pytz-2010h/README.txt

RPM 文件状态通常有四种,详细说明见下表:

1. RPM 文件的状态

状态

说明

Normal

正常,表明文件未被其他软件包修改过

not installed

未安装,表明文件未安装

Replaced

已替换,表明文件已被其他软件包修改替换过,不再是原先的文件

net shared

网络共享,表明文件处于网络共享状态

 

3.1.2   查询指定安装包的信息

3.1.2.1. 查询spec文件中rpm包版本,供应商,安装日期,URL等信息

使用rpm -q -i package-name[rpm -qi pkg-name]

如果该rpm包并未安装到系统上,即没有把该rpm包信息写入到rpm所写入的数据库中,需要指定-p—package指定具体完整的包名才可查询rpm包的描述信息。

如示例所表述:

上述示例中,仅输入ceph-common,是因为我已经安装了该rpm包,所以仅通过包名就可以检索。这些数据库的位置在/var/lib/rpm/目录下:如下图所示:

如果rpm包并未安装到系统,则需要指定完整的包名,如果不是在当前目录下,还要指定路径。

3.1.2.2. 查询rpm中文件列表信息

如果rpm包已经安装:

rpm -ql pkg-name

即可获取rpm包安装的文件列表。

如果rpm包未安装:

rpm -qpl full-pkg-name

如下示例查询file命令的rpm包,以及该包中的文件列表

[root@localhost ~]# whereisfile

file: /usr/bin/file /usr/share/file/usr/share/man/man1/file.1.gz /usr/share/man/man1p/file.1p.gz

[root@localhost ~]# rpm-qf /usr/bin/file

file-5.11-33.el7.x86_64

[root@localhost ~]# rpm-ql file

/etc/magic

/usr/bin/file

/usr/share/doc/file-5.11

/usr/share/doc/file-5.11/COPYING

/usr/share/doc/file-5.11/ChangeLog

/usr/share/doc/file-5.11/README

/usr/share/man/man1/file.1.gz

3.1.2.3. 查询指定字段信息如changelog

 

查询yum-3.4.3-154.el7.centos.noarchchangelog,可以使用

rpm -q –changelog yum

查询其他的信息,则可以指定对应的参数,可用参数如下:

query-options

       [--changelog] [-c,--configfiles] [--conflicts]

       [-d,--docfiles] [--dump] [--filesbypkg] [-i,--info]

       [--last] [-l,--list] [--obsoletes] [--provides]

       [--qf,--queryformat QUERYFMT] [-R,--requires]

       [--scripts] [-s,--state] [--triggers,--triggerscripts]

3.1.3   提取rpm包中文件

可以提取rpm包中的文件列表,来查询特定rpm包的组织结构,这在我们制作特定平台诸如aarch64,会有很大的帮助。提取命令如下:rpm2cpiofull-pkg-name | cpio -idv

在制作rpm包时,spec文件是最关键的步骤,好在我们可以在互联网上找到rpm包对应的src.rpm包,通过这种方式可以提取src.rpm包中的spec文件,照猫画虎,会提升许多的效率。

3.2  安装

rpm安装的命令格式如下:

       rpm{-i|--install} [install-options] PACKAGE_FILE ...

其中安装,升级中[install-options]是一样的,如下所示:

install-options

        [--allfiles] [--badreloc][--excludepath OLDPATH]

        [--excludedocs] [--force][-h,--hash]

        [--ignoresize][--ignorearch] [--ignoreos]

        [--includedocs][--justdb] [--nocollections]

        [--nodeps] [--nodigest][--nosignature] [--noplugins]

        [--noorder] [--noscripts][--notriggers]

        [--oldpackage][--percent] [--prefix NEWPATH]

        [--relocateOLDPATH=NEWPATH]

        [--replacefiles][--replacepkgs]

        [--test]

经常使用的命令,rpm -ivh full-pkg-name

 

3.3  升级

rpm升级的两种情形,较早版本的rpm是否存在,如果仅在较早版本存在的情况下,才升级这种情形使用-F|--freshen。而若在较早版本不存在的情况下,执行安装操作,则使用-U|--upgrade

  rpm {-U|--upgrade}[install-options] PACKAGE_FILE ...

  rpm{-F|--freshen} [install-options] PACKAGE_FILE ...

 

3.4  卸载

rpm {-e|--erase} [--allmatches] [--justdb][--nodeps] [--noscripts]  [--notriggers][--test] PACKAGE_NAME ...

 

3.5  验证

RPM Database 不仅提供了 RPM 包的查询功能,还提供了对已安装的 RPM 包进行验证的功能。通过验证,我们可以很清楚地知道一个文件变动了什么,这是 RPM 的聪明之处。本节我们来介绍几个常用的验证命令。

1. 验证某个 RPM 包的状态

命令格式:rpm -V package_name

校验时,若发现文件丢失,RPM 将输出"missing 文件名"。若有属性方面错误,RPM 将用表 2. 中的属性代码输出错误类型。

2. RPM 校验属性说明

代码

含义

S

表示文件大小

M

表示文件权限

5

表示 MD5 校验和

D

表示主从设备号

L

表示符号链接

U

表示属主

G

表示属组

T

表示最后修改时间

如果文件某项属性正常,则会显示点(.)字符,否则显示相应的表示字符。示例如下:

清单 23. 验证某个 RPM

missing   /usr/lib/python2.6/site-packages/pytz-2010h-py2.6.egg-info

S.5....T.   /usr/lib/python2.6/site-packages/pytz/__init__.py

S.5....T.   /usr/lib/python2.6/site-packages/pytz/__init__.pyc

S.5....T.   /usr/lib/python2.6/site-packages/pytz/__init__.pyo

.......T.   /usr/lib/python2.6/site-packages/pytz/reference.py

S.5....T.   /usr/lib/python2.6/site-packages/pytz/reference.pyc

S.5....T.   /usr/lib/python2.6/site-packages/pytz/tzfile.py

S.5....T.   /usr/lib/python2.6/site-packages/pytz/tzfile.pyc

S.5....T.   /usr/lib/python2.6/site-packages/pytz/tzinfo.py

S.5....T.   /usr/lib/python2.6/site-packages/pytz/tzinfo.pyc

S.5....T.   /usr/lib/python2.6/site-packages/pytz/tzinfo.pyo

4.  RPM制作

由于在日常工作中,厂商一般都会释出某项功能的源码包,这些源码包在github上这种版本管理工具上大多都能找到,但可能并没有提供对应的rpm包,或者说开发任务在aarch64这类的平台架构上,尽管有x86_64rpm包,由于是在x86平台上编译的,所以直接放在arm架构的linux中,无法正常工作,因此需要我们把源代码获取到,在目标机器上重新编译,才能够生成更加高效的、定制化功能的rpm,更加适合于开发的机器。因而掌握如何制作rpm包,熟悉RPM制作流程,便非常重要。一种常见的情形是,厂商提供了源码包,获取之后,如何把源码包打成rpm包,这样可以省去每次安装重新编译耗时的操作。同时让rpm这个软件包管理工具去管理依赖性,较为省时省力,部署时也比较方便。

4.1  RPM命名规范

上图是我们通过rpm -q列举出系统已经安装过的,包名中含有“python”关键字的rpm包。通过上面几个rpm包的名字,简要叙述rpm包命名规范。通过以上几个例子可以归纳出rpm命名规范为:

name-version-release.arch.rpm

python-2.7.5-58.el7.x86_64.rpm为例,可以看到该包名为python,版本为2.7.5release58.3el7,release表示在源代码基础上编译释出的次数,58表明,python这个包已经由供应商发布了58次,arch平台架构,表示该rpm包编译的机器架构为x86_64,x8664位。目前常见的硬件架构为目前RPM支持的平台有:i386i586i686sparcalphax86_64, aarch64等。

另外如果为rpm源码包,则尾缀为src.rpm, 这种源码rpm包包含源码包,补丁文件,spec文件,是我们学习制作rpm包非常好的素材。.rpm.src.rpm,RPM包类型的后缀,.rpm是编译好的二进制包,可用rpm命令直接安装;.src.rpm表示是源代码包,需要安装源码包生成源码,并对源码编译生成.rpm格式的RPM包,就可以对这个RPM包进行安装了。

4.2  平台架构

平台架构,这个暂时不需要做过多的了解,只需要知道常见的平台架构是x86_64,可以使用rpm -qa命令列举出系统中已经安装的rpm包,查看其中的arch部分,noarch表示该rpm包不受架构影响,其中的源码多为脚本,nodejs类似的可执行文件。在你的本机上执行uname -a,可以查看当前linux系统的架构:

[root@localhost ~]# uname -a

Linux localhost.localdomain 3.10.0-693.el7.x86_64#1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64x86_64 x86_64 GNU/Linux

[root@localhost ~]# uname -r

3.10.0-693.el7.x86_64

标红部分el7表示该系统为redhat7 x86_64表示是x8664位系统。在当前系统上执行rpmbuild命令,打出来的包,会自动添加上平台信息。可以在www.rpmfind.comwww.rpmsearch.com, 两个网站上找到较多的rpm包,各种平台架构的都有。http://mirror.centos.org/centos/http://vault.centos.org/也提供了较多的rpm包和src.rpm包,但主要是为centos系统上的rpm包。

4.3  RPM制作前提—rpmdev-tools

  1. Planning what you want             计划做什么rpm包。软件的?库的?

  2. Gathering the software topackage  收集原材料,即收集源码包

  3. Patch the software as need        如果需要打补丁,收集补丁文件。

  4. Outling any dependenies    确定依赖关系包

  5. Building RPMs                     开始动手制作RPM

  1. Set up the directory stucture 设定好目录结构,我们在这些目录中制作我们的RPM包,我们需要下列目录

    BUILD   源代码解压后的存放目录

    RPMS    制作完成后的RPM包存放目录,里面有与平台相关的子目录

    SOURCES  收集的源材料,补丁的存放位置

    SPECS    SPEC文件存放目录

    SRPMS   存放SRPMS生成的目录

  2. Place the Sources in the rightdirectory   把源材料放到正确的位置

  3. Create a spec file that tellrpmbuild command what to do 创建spec文件,这是纲领文件,rpmbuild命令根据spec文件来制作合适的rpm

  4. Build the source and binaryRPMS 制作src或二进制rpm

  1. Test RPMS 测试制作的PRM

  2. Add signature for RPM  RPM包添加数字签名签名

    制作过程简要的说就是上面的几个步骤,另外要注意的是在制作RPM包的过程中,一定不要使用root用户,而要使用普通用户,root的可能会因为代码问题导致毁灭的后果。

    另外rpmbuild制作rpm包的目录结构可以通过rpmdev-tools包提供的命令rpmdev-setuptree,在当前用户的主文件夹下自动创建。如下所示:

[centos@localhost ~]$ rpmdev-setuptree

[centos@localhost ~]$ ls

rpmbuild

[centos@localhost ~]$ ls rpmbuild/

BUILD RPMS  SOURCES  SPECS SRPMS

可以看到默认创建了5个目录,在是rpm制作过程中会自动创建BUILDROOT作为安装的虚拟根目录。另外,rpmdev-tools这个rpm包可能需要自己手动下载,可以在rpmfind网站获取。安装即可使用。

4.4  RPM制作过程简述

整个rpm制作都是在$HOME/rpmbuild目录这个制作车间下完成的。BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS六个子目录。BUILD是解压源码包的目录;BUILDROOT是最后生成rpm包的临时安装目录;RPMS存放最终生成的rpm二进制包;SPECS用来存放spec文件;SRPMS存放最终生成的rpm源码包。倘若这些目录不存在我们运行rpmdev-setuptree命令就会在当前用户目录下的rpmbuild目录下生成上述六个子目录。spec文件可以放到任何地方,但是自己的源码包(.tar.gz)必须放到SOURCES目录下,否则rpmbuild编译时会找不到指定的源码包。而上述的这些目录默认是在用户目录下的,即$HOME/rpmbuild,我们也可以自定义,这个路径是在/usr/lib/rpm/macros文件里面%_topdir的宏变量来定义。我们可以在自己的主目录下建立一个名为.rpmmacros的隐藏文件,然后在里面重新定义%_topdir,指向一个新的目录名。通常情况下.rpmmacros文件里一般只有一行内容,比如:

%_topdir    $HOME/myrpmbuild

然后,再运行rpmdev-setuptree命令即可在/myrpmbuild生成其他子目录。

另外我们可以通过运行

rpmbuild –showrc | grep _topdir

来查看rpmbuild为我们提供的宏定义。

打包的过程与源码编译的过程是一样的,首先是源码.tar.gz解压缩,解压缩过后再BUILD目录下生成目录name-version目录,内容为源码包解压生成的文件。并在该目录下编译[./configure生成Makefilemake利用生成的Makefile进行编译],然后通过make install安装软件到指定的目录,一般执行的命令为make install DESTDIR=$RPM_BUILD_ROOT, 在安装过程需要重新组织生成的文件结构,该过程针对$RPM_BUILD_ROOT目录下来说的。也要把BUILD/name-version/目录下的README.rst INSTALLCHANGES等文件放置在$RPM_BUILD_ROOT目录下需要的结构,然后在%files字段列出需要的文件,制作好spec文件通过rpmbuild -ba name.spec即可同时制作rpm包和src.rpm包。也可分部执行,查看每个步骤执行的具体过程。

-bp       #只执行spec%pre段(解源代码包并打补丁,只是准备阶段)

-bc       #执行spec%pre%build段(准备并编译)

-bi       #执行spec%pre %build%install(准备,编译并安装)

-bl        #检查spec中的%file段(查看文件是否齐全)

-ba        #建立源码与二进制包(常用)

-bb        #只建立二进制包

-bs        #只建立源码包

 

vi tengine.spec   下面是一个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 其中%{dist}表示的含义是如果定义了dist宏,就使用,没有定义就不适用。Redhat 7默认定义为el7.centos

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  

Vendor:         TaoBao.com 

Source0:        %{name}-%{version}.tar.gz   

#定义用到的source,也就是你收集的,可以用宏来表示,也可以直接写名字,上面定义的内容都可以像上面那样引用 

#patch0:            a.patch                 #如果需要补丁,依次写 

BuildRoot:      %_topdir/BUILDROOT         

#这个是软件make install 的测试安装目录,也就是测试中的根,我们不用默认的,我们自定义,

#我们可以来观察生成了哪此文件,方便写file区域 

BuildRequires:  gcc,make                           #制作过程中用到的软件包 

Requires:       pcre,pcre-devel,openssl,chkconfig  #软件运行需要的软件包,也可以指定最低版本如 bash >= 1.1.1 [注意>=两边均有一个空格]

%description                                       #软件包描述,尽情的写吧 

It is a Nginx from Taobao.                         #描述内容 

 

###  2.The Prep section 准备阶段,主要目的解压sourcecd进去 

 

%prep                                              #这个宏开始 

%setup -q                                          #这个宏的作用静默模式解压并cd 

#%patch0 -p1                                       #如果需要在这打补丁,依次写 

 

###  3.The Build Section 编译制作阶段,主要目的就是编译 

%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                                

rm -rf %{buildroot}                #先删除原来的安装的,如果你不是第一次安装的话 

make install DESTDIR=%{buildroot} [%{buildroot}可以使用$RPM_BUILD_ROOT替换]

#DESTDIR指定安装的目录,而不是真实的安装目录,%{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 

rm -rf %{buildroot} 

     

###  6.file section 要包含的文件 

%files  

%defattr (-,root,root,0755)   #设定默认权限,如果下面没有指定权限,则继承默认 

/etc/           #下面的内容要根据你在%{rootbuild}下生成的来写     

/usr/ 

/var/ 

     

###  7.chagelog section  改变日志段 

%changelog 

*  Fri Dec 29 2012 laoguang  - 1.0.14-1 

- Initial version 

 

spec文件中有以下重要的段落

%description描述段落


%prep
echo "
预处理脚本程序(prep)开始执行"
%setup


%build 
编译段落

./configure
echo "
编译连接脚本程序(build)开始执行
"
make

%install  安装段
echo "
安装脚本程序(install)开始执行"
make install DESTDIR=$RPM_BUILD_ROOT

%clean  清理段
echo "
建包结束后清理脚本程序(clean)开始执行"

%pre  安装前执行脚本 诸如创建用户,用户组
echo "
安装前执行脚本程序(pre)开始执行"

%post  安装后执行脚本,诸如重新加载服务,重启服务
echo "
安装后执行脚本程序(post)开始执行"

%preun  卸载前执行脚本
echo "
卸载前执行脚本程序(preun)开始执行"

%postun  卸载之后执行脚本
echo "
卸载后执行脚本程序(postun)开始执行"

%files  文件段列举要打包进rpm文件列表。
打包的文件列表

%changelog  变化段
*Sun May 31 2009 Songquanheng 1.30-2
- descriptive information about changes

4.5 SPEC文件深度说明

在制作RPM包的过程中,最关键的一个步骤就是spec文件的撰写。在把源码包,补丁文件,放置在$HOME/rpmbuild/SOURCES/目录下之后,切换到%{_topdir}/SPECS/目录下,通过下列命令创建一个spec文件来指导rpm包的创建。

rpmdev-newspec nginx.spec

4.5.1   RPM描述信息

每个rpm包都有一些描述信息,诸如包名,版本信息,发布次数,URL,描述信息,概要,许可证等,这些信息可以通过rpm -qi pkg-name检索到。这些信息均在spec文件中定义,由域定义。

4.5.1.1. Name

该字段定义了rpm包的名称,后面可以使用%{name}引用。

Name:          pkg-name

4.5.1.2. Version

该字段定义rpm包版本信息,后面可以使用%{release}引用。

Version:    version-info

 

4.5.1.3. Release

该字段定义rpm发布次数,后面可以使用%{release}引用

Release:            1%{?dist}

其中%{dist}宏的含义是,如果定义了dist宏,就使用该变量指定的值,没有定义就不使用。在redhat7上,默认该值为el7.centos

4.5.1.4. Group

该字段定义了rpm的所属组。建议使用标准分组。

4.5.1.5. Summary

该字段的作用是简要描述该RPM包,以nginx为例,该段可以定义如下:

Summary  A high performance webserver and reverse proxy server

 

4.5.1.6. License

该字段描述许可证信息,常见的LicenseBSDGPL等。

4.5.1.7. Packager

该字段描述打包者的信息,可以使用名字或者邮箱

4.5.1.8. URL

该字段可以填写该RPM包源码包供应商的网址。

4.5.1.9. Source

该字段填写的是源码包,如果有多个源码包可以顺序编号。Source0, Source1,Source2

Source0: %{name}-%{version}.tar.gz

Source1: http/nginx.org/%{name}-%{version}.tar.gz

虽然可以写成带有url的报名,但实际工作时,仅以最后的源代码包名有效,不会去网上下载。

4.5.1.10.    Patch

该字段描述的是补丁信息。与Source段一样,当有多个补丁时,可以以次序编号:Patch0, Patch1, Patch2

%prep字段可以通过下列命令打入补丁。

%patch0 -p0

4.5.1.11.    Description

该字段描述该软件包的描述信息,可以有多行,中间用空行隔开。建议每行字符数目不要超过75个。

%description

Nginx is a web server and a reverse proxy serverfor HTTP, SMTP, POP3 and IMAP protocols, with a strong focus on highconcurrency, performance and low memory usage.

4.5.2   依赖关系

依赖关系定义了一个包正常工作需要依赖的其他包,RPM在升级、安装、删除的时候会确保依赖关系得到满足。RPM支持4种依赖:

Requires: 包依赖其他包所提供的功能。

Provides:这个包提供的功能。

Conflicts:一个包和其他包冲突的功能

Obsoletes,其他包提供的功能已经不推荐使用了,这通常是其他包的功能修改了,老版本不再使用了,可以在以后的版本中会被废弃。

4.5.2.1. BuildRequires

编译时依赖,可以同时指定多个。顺序列出即可。

BuildRequires:   pcre

BuildRequires:   openssl

BuildRequires:   zlib

 

4.5.2.2. Requires

rpm包所依赖的软件包名称,可以用>=<=表示大于或小于某一特定版本,例如:

libpng-devel >= 1.0.20 zlib

※“>=”号两边需用空格隔开,而不同软件名称也用空格分开

 还有例如PreReqRequires(pre)Requires(post)Requires(preun)Requires(postun)BuildRequires等都是针对不同阶段的依赖指定。该字段表示的是在该rpm包安装之后所提供的功能在运行过程中依赖的功能,尽管我们可以强制安装rpm包,不考虑其依赖,但这通常是非常不好的行为。一定要确保该字段定义的RPM包提前安装。

4.5.3   %prep

%prep  预处理脚本

执行umask 022,在创建文件和目录时的默认掩码。之后cd BUILD目录之中。rm -rf nginx-1.10.3
%setup -n %{name}-%{version} 
把源码包解压并放好,通常是从$(HOME)/SOURCES解压到$(HOME)/BUILD/%{name}-%{version}中。

一般用%setup -c就可以了,但有两种情况:一就是同时编译多个源码包,二就是源码的tar包的名称与解压出来的目录不一致,此时,就需要使用-n参数指定一下了。

%patch 
打补丁
通常补丁都会一起在源码tar.gz包中,或放到SOURCES目录下。一般参数为:
%patch -p1
使用前面定义的Patch补丁进行-p1是忽略patch的第一层目录
%Patch2 -p1 -b xxx.patch
打上指定的补丁,-b是指生成备份文件

◎补充一下

引用

%setup不加任何选项,仅将软件包打开。
%setup -n newdir
将软件包解压在newdir目录。

%setup -c
解压缩之前先产生目录。

%setup -b num
将第numsource文件解压缩。

%setup -T
不使用default的解压缩操作。

%setup -T -b 0
将第0个源代码文件解压缩。

%setup -c -n newdir
指定目录名称newdir,并在此目录产生rpm套件。

%patch
最简单的补丁方式,自动指定patch level

%patch 0
使用第0个补丁文件,相当于%patch ?p0

%patch -s
不显示打补丁时的信息。

%patch -T
将所有打补丁时产生的输出文件删除。

在执行%prep阶段时,程序会首先cd$HOME/BUILD目录下,然后执行利用gzip命令结合tar命令解压缩源代码包

/usr/bin/gzip/home/sqh/rpmbuild/SOURCES/nginx-1.10.3.tar.gz | tar -xf –

这样就在BUILD目录下,解压缩了源代码包。在BUILD目录下生成了目录nginx-1.10.3。其内容为源码包解压之后的内容。

以上的共总是%setup -q -n %{name}-%{version},所制定的。

若在之后添加了shell脚本,则会依次执行。

4.5.4   %build

在构建段,开始在BUILD/nginx-1.10.3/目录下生成Makefile,由该文件指导编译过程。通常会含有两个过程。./configuremake。其中./configure会生成Makefile文件。Make命令会执行编译。

./configure

--prefix=/etc/nginx

--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.pid

--lock-path=/var/run/nginx.lock

--http-client-body-temp-path=/var/cache/nginx/client_temp

--http-proxy-temp-path=/var/cache/nginx/proxy_temp

--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp

--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp

--http-scgi-temp-path=/var/cache/nginx/scgi_temp

--user=nginx --group=nginx --with-http_ssl_module

--with-http_realip_module --with-http_addition_module

--with-http_sub_module --with-http_dav_module

--with-http_flv_module --with-http_mp4_module

--with-http_gunzip_module --with-http_gzip_static_module

--with-http_random_index_module --with-http_secure_link_module

--with-http_stub_status_module --with-http_auth_request_module

--with-mail --with-mail_ssl_module --with-file-aio --with-ipv6

--with-http_spdy_module

--with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions-fstack-protector

--param=ssp-buffer-size=4 -m64 -mtune=generic'

需要注意的时,在制作RPM包时候,可以通过./configure–help查看源代码编译时提供了那些选项,有选择的开启功能和模块。定制某些功能,精简某些功能让rpm更加适配自己的系统。./configure的功能选项是一定要去查看的,然后也要添加make命令进行编译。

./configure –prefix=$RPM_BUILD_ROOT

make

如果为python setup.py intall 形式安装的源码包,则可以使用如下形式的编译命令

%{__python} setup.py build

4.5.5   %install

需要弄清楚编译和安装的概念,在执行编译过后,系统会生成一些可执行文件,但rpmbuild的过程是制作rpm包的过程,因此我们并没有真正的把编译生成的二进制程序,配置文件,文档真正的写入系统下,而是在要给虚拟的目录,该目录在centos7下如果没有指定,则为$HOME/BUILDROOT

注意区分$RPM_BUILD_ROOT$RPM_BUILD_DIR $RPM_BUILD_ROOT是指开头定义的BuildRoot,而$RPM_BUILD_DIR通常就是指/usr/src/asianux/BUILD,其中,前面的才是%file需要的。

在实际工作中,我通过打印$RPM_BUILD_ROOT,发现该变量的值为BUILDROOT/%{name}-%{version}-%{release}.centos.aarch64。不过也不用太过在意。需要弄清楚的概念是我们在安装段%install,要把需要打包进入rpm包的文件放入$PM_BUILD_ROOT

通常在这个段落前面的两条命令如下:

%install

rm -rf $RPM_BUILD_ROOT

make install DESTDIR=$RPM_BUILD_ROOT

nginx制作的过程中,执行上述命令会在BUILDROOT/nginx-1.10.3-1el7.centos.aarch64/生成usr目录。但编译安装生成的目录通常不是我们想要的目录结构,因此我们需要重新组织该文件目录下[$RPM_BUILD_ROOT]的结构,生成新的目录,挪动文件的位置,并且要把需要的文档文件、配置文件从BUILD目录移动到$RPM_BUILD_ROOT目录下。通常也要把编译生成的可执行文件放在如/usr/bin/等可执行的目录,因而要在$RPM_BUILD_TOOT创建usr/bin/目录下,把可执行文件nginxcopy进入该目录。注意:此时当前目录仍然为BUILD目录。

由于在$RPM_BUILD_ROOT/目录下生成了usr目录,所以仍要安装目录etc, var等目录。

4.5.6   %clean

清理段负责清理$RPM_BUILD_ROOT,通常只有一个命令,负责清理虚拟根目录$RPM_BUILD_ROOT

rm -rf $RPM_BUILD_ROOT

4.5.7   %files

在制作rpm包的过程中,有两个部分是最关键的,一个是%install阶段,另外一个就是%files段。在%install字段,可能在$RPM_BUILD_ROOT目录下生成了许多的目录结构,但我们需要真正在rpm-ivh安装时安装进入系统的文件可能只有一部分,并不包含源码和debug之类的文件。因此我们要在%files列出的文件是我们要打包进入rpm的文件列表。

定义软件所包含的文件,分为三类:说明文档(doc),配置文件(config)及执行程序,还可以定义文件存取权限,拥有者及组别。

这里会在虚拟根目录下进行,千万不要写绝对路径,而应该是用宏或变量表示相对路径。

%defattr(-, root, root, -)指定包装文件的属性,-表示默认属性,对文本文件是0644,对可执行文件是0755.

%files

%license LICENSE

%doc CHANGES README README.dynamic

%{_datadir}/nginx/html/*

%{_bindir}/nginx-upgrade

%{_sbindir}/nginx

%{_datadir}/vim/vimfiles/ftdetect/nginx.vim

%{_datadir}/vim/vimfiles/syntax/nginx.vim

%{_datadir}/vim/vimfiles/indent/nginx.vim

%{_mandir}/man3/nginx.3pm*

%{_mandir}/man8/nginx.8*

%{_mandir}/man8/nginx-upgrade.8*

%{_unitdir}/nginx.service

%config(noreplace) %{_sysconfdir}/nginx/fastcgi.conf

%config(noreplace) %{_sysconfdir}/nginx/fastcgi.conf.default

%config(noreplace) %{_sysconfdir}/nginx/fastcgi_params

%config(noreplace) %{_sysconfdir}/nginx/koi-utf

%config(noreplace) %{_sysconfdir}/nginx/koi-win

%config(noreplace) %{_sysconfdir}/nginx/mime.types

%config(noreplace) %{_sysconfdir}/nginx/mime.types.default

%config(noreplace) %{_sysconfdir}/nginx/nginx.conf

%config(noreplace) %{_sysconfdir}/nginx/nginx.conf.default

%config(noreplace) %{_sysconfdir}/nginx/scgi_params

%config(noreplace) %{_sysconfdir}/nginx/scgi_params.default

%config(noreplace) %{_sysconfdir}/nginx/uwsgi_params

%config(noreplace) %{_sysconfdir}/nginx/uwsgi_params.default

%config(noreplace) %{_sysconfdir}/nginx/win-utf

%config(noreplace) %{_sysconfdir}/logrotate.d/nginx

%attr(700,%{nginx_user},%{nginx_user}) %dir %{_localstatedir}/lib/nginx

%attr(700,%{nginx_user},%{nginx_user}) %dir%{_localstatedir}/lib/nginx/tmp

%attr(700,%{nginx_user},%{nginx_user})   %{_localstatedir}/log/nginx

%dir %{_libdir}/nginx/modules

上述代码片是在nginx中使用的%files字段。

在字段中要注意几个方面。%doc字段是列举出要在rpm-ivhrpm包作为文档的文件,该文件应在BUILD/nginx-1.10.3/目录下存在,并且会被复制到$RPM_BUILD_ROOT/usr/share/doc,因此确保在%install阶段创建目录$RPM_BUILD_ROOT/usr/share/doc

mkdir -p $RPM_BUILD_ROOT/usr/share/doc/

%doc CHANGES README 会自动把BUILD/nginx-1.10.3目录下的CHAANGES README等文档文件放入相应位置$RPM_BUILD_ROOT/usr.share/doc/nginx-1.10.3目录下。

%config(noreplace) %{_sysconfdir}/nginx/fastcgi.conf.default

%config(noreplace) %{_sysconfdir}/nginx/fastcgi_params

上述代码片段,%config表示后面的文件为配置文件,如果是升级一个rpm包,肯定是不能让之前配置的配置文件直接被rpm包中的新文件给替换掉的,因此我们可以标记noreplace,保持原有的文件,并把要安装的文件名字定义成fastcgi.conf.default

%attr(700,%{nginx_user},%{nginx_user}) %dir %{_localstatedir}/lib/nginx

%attr(700,%{nginx_user},%{nginx_user}) %dir%{_localstatedir}/lib/nginx/tmp

%attr(700,%{nginx_user},%{nginx_user})   %{_localstatedir}/log/nginx

上面的%attr(700, nginx, nginx)则是定义该文件的可执行权限,属主,属组。

若执行

rpmbuild -bi nginx.spec

此时因为仅仅执行到了安装阶段完毕,因此我们可以切换进入BUILDROOT/nginx-1.10.3-el7.centos.aarch64/目录下,通过tree命令列举出该目录【即$RPM_BUILD_ROOT】下的文件结构。

可以发现在usr/src/存在debug目录,其内容为许多源代码文件,而这些文件是我们在rpm安装时不需要的文件,因而我们可以在%files字段中不列举该目录。原则是,需要什么列举什么文件。如果该目录下有许多文件,也可以仅列举出一个目录即可。如下

%{_localstatedir}/cache/nginx/

%{_datadir}/doc/[其目录下应有几个文件。]

4.5.8   %changelog

每次软件的更新内容可以记录在这里,保存到发布的软件包之中,以便查询只用。注意保证格式的正确。

%changelog

* Wed Feb  8 2017 Joe Orton - 1:1.10.3-1

- update to upstream release 1.10.3

 

* Mon Oct 31 2016 Jamie Nguyen -1:1.10.2-1

- update to upstream release 1.10.2

 

* Tue May 31 2016 Jamie Nguyen -1:1.10.1-1

- update to upstream release 1.10.1

 

* Sun May 15 2016 Jitka Plesnikova -1:1.10.0-4

- Perl 5.24 rebuild

4.6 rpmbuild 常用宏定义

通过命令rpmbuild –showrc | grep _var查看实现代码。另外直接通过rpm --eval "%{macro}"来查看具体对应路径。

比如我们要查看%{_bindir}的路径,就可以使用命令rpm --eval "%{ _bindir}"来查看。

另外,所有的宏都可以在/usr/lib/rpm/macros里找到。

下面是宏对应路径一览表:

Macros mimickingautoconf variables

%{_sysconfdir}        /etc

%{_prefix}            /usr

%{_exec_prefix}      %{_prefix}

%{_bindir}            %{_exec_prefix}/bin   /usr/bin

%{_lib}               lib (lib64on 64bit systems)

%{_libdir}           %{_exec_prefix}/%{_lib}

%{_libexecdir}       %{_exec_prefix}/libexec

%{_sbindir}          %{_exec_prefix}/sbin  /usr/sbin

%{_sharedstatedir}    /var/lib     /var/lib

%{_datadir}          %{_prefix}/share   /usr/share

%{_includedir}       %{_prefix}/include  /usr/include

%{_oldincludedir}    /usr/include  

%{_infodir}          /usr/share/info

%{_mandir}           /usr/share/man

%{_localstatedir}     /var      /var

%{_initddir}         %{_sysconfdir}/rc.d/init.d    /etc/rc.d/init.d

%{_topdir}           %{getenv:HOME}/rpmbuild

%{_builddir}         %{_topdir}/BUILD

%{_rpmdir}           %{_topdir}/RPMS

%{_sourcedir}         %{_topdir}/SOURCES

%{_specdir}          %{_topdir}/SPECS

%{_srcrpmdir}        %{_topdir}/SRPMS

%{_buildrootdir}    %{_topdir}/BUILDROOT

%{_var}               /var

%{_tmppath}           %{_var}/tmp

%{_usr}               /usr

%{_usrsrc}            %{_usr}/src

%{_docdir}           %{_datadir}/doc

一个简单的方式,比如说你想要使用/usr/lib/systemd/system目录所简化的目录,可以通过以下的方式

rpmbuild –showrc | grepsystem

就可以查询到

_unitdir   /usr/lib/system/system

 

4.7  Install 命令

%install段经常会出现的命令是install或者%{__install},两者是一样的,没有什么太大的区别,使用%{__install}可以解决跨平台的问题。

install命令的主要作用是install -copy files and set attributes。拷贝文件和设置属性。它的作用比cp命令更加强大。常用的语法结构如下:

SYNOPSIS

      install [OPTION]... [-T] SOURCE DEST

      install [OPTION]... SOURCE... DIRECTORY

      install [OPTION]... -t DIRECTORY SOURCE...

      install [OPTION]... -d DIRECTORY...

In  the  first three forms, copy SOURCE to DEST or multiple SOURCE(s) to the existingDIRECTORY, while setting permission modes and owner/group.  In the 4th form, create all components of thegiven DIRECTORY(ies).翻译一下:在前三种形式中,拷贝SOURCEDEST,或者拷贝多个SOURCE到已存在的目录,在设置权限模式和所有者/所属组的同时。在第四种模式中,创建给定目录所有组成部分。

 

     -d, --directory

              treat all argumentsas directory names; create all components of the specified directories

 

       -D     create all leading components of DESTexcept the last, then copy SOURCE to DEST

 

       -g, --group=GROUP

              set groupownership, instead of process' current group

 

       -m, --mode=MODE

              set permission mode(as in chmod), instead of rwxr-xr-x

 

       -o, --owner=OWNER

              set ownership(super-user only)

 

       -p, --preserve-timestamps

              applyaccess/modification times of SOURCE files to corresponding destination files

你可能感兴趣的:(制作RPM包规范和rpm相关命令)