zoukankan      html  css  js  c++  java
  • 制作RPM包

    RPM包制作过程

    1.1 前期工作

    1)创建打包用的目录rpmbuild/{BUILD,SPECS,RPMS, SOURCES,SRPMS}

    建议使用普通用户,在用户家目录中创建

    2)确定好制作的对象,是源码包编译打包还只是一些库文件打包

    3)编写SPEC文件

    4)开始制作

    1.2 RPM制作过程

    1)读取并解析 filename.spec 文件

    2)运行 %prep 部分来将源代码解包到一个临时目录,并应用所有的补丁程序。

    3)运行 %build 部分来编译代码。

    4)运行 %install 部分将代码安装到构建机器的目录中。

    5)读取 %files 部分的文件列表,收集文件并创建二进制和源 RPM 文件。

    6)运行 %clean 部分来除去临时构建目录。

    补充说明:

    BUILD目录:制作车间,二进制tar.gz包的解压后存放的位置,并在此目录进行编译安装

    SPECS目录:存放SPEC文件

    RPMS目录:存放制作好的rpm包

    SOURCES目录:存放源代码

    SRPMS目录:存放编译好的二进制rpm包

    BUILDROOT目录:此目录是在BUILD目录中执行完make install之后生成的目录,里面存放的是编译安装好的文件,他是./configure中—prefix指定path的根目录

    1.3制作工具:rpmbuild

    制作过程的几个状态

    rpmbuild -bp 执行到%prep

    rpmbuild -bc 执行到%build中的config

    rpmbuild -bi 执行至%build中的install

    rpmbuild -ba 编译后做成rpm包和src.rpm包

    rpmbuild -bs 仅制作src.rpm包

    rpmbuild -bb 仅制作rpm包

    2.SPEC文件
    2.1 spec文件参数:

    自定义软件包基本参数:

    Name 软件包名字

    Version 软件包版本

    Release 软件包修订号

    Summary 软件包简单描述

    Group 软件包所属组。必须是系统定义好的组

    License 软件授权方式,通常就是GPL

    Vendor 软件包发型厂商

    Packager 软件包打包者

    URL 软件包的url

    Source 定义打包所需的源码包,可以定义多个,后面使用%{SOURCE}调用

    Patch 定义补丁文件,后面可以使用%{Patch}调用

    BuildRoot 定义打包时的工作目录

    BuildRequires 定义打包时依赖的软件包

    Requires 定义安装时的依赖包,形式为Package name 或者 Package >= version

    Prefix %{_prefix}| %{_sysconfdir} : %{_prefix} 这个主要是为了解决今后安装rpm包时,并不一定把软件安装到rpm中打包的目录的情况。这样,必须在这里定义该标识,并在编写%install脚本的时候引用,才能实现rpm安装时重新指定位置的功能

    %{_sysconfdir} 这个原因和上面的一样,但由于%{_prefix}指/usr,而对于其他的文件,例如/etc下的配置文件,则需要用%{_sysconfdir}标识

    %package 定义一个子包

    %description 详细描述信息

    自定义打包参数;

    %prep 预处理段,默认是解压源码包,可以自定义shell命令和调用RPM宏命令

    %post rpm安装后执行的命令,可以自定义shell命令和调用RPM宏命令

    %preun rpm卸载前执行的命令,可以自定义shell命令和调用RPM宏命令

    %postun rpm卸载后执行的命令,可以自定义shell命令和调用RPM宏命令

    %patch 打补丁阶段

    %build 编译安装段,此段包含./configure和 make 安装阶段

    %install 安装阶段,会把编译好的二进制文件安装到BUILDROOT为根的目录下

    %files 文件段,定义软件打包时的文件,分为三类--说明文档(doc),配置文件(config)及执行程序,还可定义文件存取权限,拥有者及组别。其路径为相对路径

    %changelog 定义软件包修改的日志

    2.2补充:

    Group: 
    软件包所属类别,具体类别有:
    Amusements/Games (娱乐/游戏)
    Amusements/Graphics(娱乐/图形)
    Applications/Archiving (应用/文档)
    Applications/Communications(应用/通讯)
    Applications/Databases (应用/数据库)
    Applications/Editors (应用/编辑器)
    Applications/Emulators (应用/仿真器)
    Applications/Engineering (应用/工程)
    Applications/File (应用/文件)
    Applications/Internet (应用/因特网)
    Applications/Multimedia(应用/多媒体)
    Applications/Productivity (应用/产品)
    Applications/Publishing(应用/印刷)
    Applications/System(应用/系统)
    Applications/Text (应用/文本)
    Development/Debuggers (开发/调试器)
    Development/Languages (开发/语言)
    Development/Libraries (开发/函数库)
    Development/System (开发/系统)
    Development/Tools (开发/工具)
    Documentation (文档)
    System Environment/Base(系统环境/基础)
    System Environment/Daemons (系统环境/守护)
    System Environment/Kernel (系统环境/内核)
    System Environment/Libraries (系统环境/函数库)
    System Environment/Shells (系统环境/接口)
    User Interface/Desktops(用户界面/桌面)
    User Interface/X (用户界面/X窗口)
    User Interface/X Hardware Support (用户界面/X硬件支持)

    %setup 的用法

    %setup 不加任何选项,仅仅打开源码包

    %setup -n newdir 将软件包解压至新目录(重命名解压的包),默认

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

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

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

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

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

    %setup -q 解压不输出信息

    %Patch用法

    先使用Patch{n}定义补丁包,然后使用%patch{n}或者%{patch{n}}来调用打补丁

    补丁号命名规则

    0-9 Makefile、configure 等的补丁

    10-39 指定功能或包含他的文件的补丁

    40-59 配置文件的补丁

    60-79 字体或字符补丁

    80-99 通过 xgettexize 得到的目录情况的补丁

    100- 其他补丁

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

    %patch 0 使用第0个补丁文件,相当于%patch -p 0。

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

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

    %patch -b name 在打补丁之前,将源文件加入name,缺省为.org

    %file用法

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

    %attr(600,work,work) 指定特定的文件目录权限

    fattr (-,root,root)

    本段是文件段,用于定义构成软件包的文件列表,那些文件或目录会放入rpm中,分为三类-说明文档(doc),配置文件(config)及执行程序,还可定义文件存取权限,拥有者及组别。

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

    ※特别需要注意的是:%install部分使用的是绝对路径,而%file部分使用则是相对路径,虽然其描述的是同一个地方。千万不要写错。

    %files -f %{name}.lang tui

    file1 #文件中也可以包含通配符,如*

    file2

    directory #所有文件都放在directory目录下

    %dir /etc/xtoolwait #仅是一个空目录/etc/xtoolwait打进包里

    %doc 表示这是文档文件,因此如安装时使用--excludedocs将不安装该文件,

    %doc /usr/X11R6/man/man1/xtoolwait.* #安装该文档

    %doc README NEWS #安装这些文档到/usr/share/doc/%{name}-%{version} 或者 /usr/doc或者

    %docdir #定义说明文档的目录,例如/root,在这一语句后,所有以/root开头的行都被定义为说明文件。

    %config /etc/yp.conf #标志该文件是一个配置文件,升级过程中,RPM会有如下动作。

    %config(missisgok) /etc/yp.conf 此配置文件可以丢失,即使丢失了,RPM在卸载软件包时也不认为这是一个错误,并不报错。一般用于那些软件包安装后建立的符号链接文件,

    /etc/rc.d/rc5.d/S55named文件,此类文件在软件包卸载后可能需要删除,所以丢失了也不要紧。

    %config(noreplace) /etc/yp.conf

    #该配置文件不会覆盖已存在文件(RPM包中文件会以.rpmnew存在于系统,卸载时系统中的该配置文件会以.rpmsave保存下来,如果没有这个选项,安装时RPM包中文件会以.rpmorig存在于系统 )

    覆盖已存在文件(没被修改),创建新的文件加上扩展后缀.rpmnew(被修改)

    %{_bindir}/*

    %config /etc/aa.conf

    %ghost /etc/yp.conf #该文件不应该包含在包中,一般是日志文件,其文件属性很重要,但是文件内容不重要,用了这个选项后,仅将其文件属性加入包中。

    %attr(mode, user, group) filename #控制文件的权限如%attr(0644,root,root) /etc/yp.conf

    如果你不想指定值,可以用-

    %config %attr(-,root,root) filename #设定文件类型和权限

    fattr(-,root,root) #设置文件的默认权限,-表示默认值,对文本文件是0644,可执行文件是0755

    %lang(en) %{_datadir}/locale/en/LC_MESSAGES/tcsh* #用特定的语言标志文件

    %verify(owner group size) filename #只测试owner,group,size,默认测试所有

    %verify(not owner) filename #不测试owner,测试其他的属性

    所有的认证如下:

    group: 认证文件的组

    maj: 认证文件的主设备号

    md5: 认证文件的MD5

    min: 认证文件的辅设备号

    mode: 认证文件的权限

    mtime: 认证文件最后修改时间

    owner: 认证文件的所有者

    size: 认证文件的大小

    symlink:认证符号连接

    如果描述为目录,表示目录中出%exclude外的所有文件。

    %files

    fattr(-,root,root)

    %doc

    %{_bindir}/*

    %{_libdir}/liba*

    %{_datadir}/file

    %{_infodir}/*

    %{_mandir}/man[15]/*

    %{_includedir}

    %exclude %{_libdir}/debug

    (%exclude 列出不想打包到rpm中的文件。※小心,如果%exclude指定的文件不存在,也会出错的。)

    如果把

    %files

    fattr(-,root,root)

    %{_bindir}

    写成

    %files

    fattr(-,root,root)

    /usr/bin

    则打包的会是根目录下的/usr/bin中所有的文件。

    %files libs

    fattr(-,root,root)

    %{_libdir}/*so.*

    %files devel

    �fattr(-,root,root)

    %{_includedir}/*

    install的用法

    -b:为每个已存在的目的地文件进行备份;

    -d:创建目录,类似mkdir -p

    -D:创建目的地前的所有目录,然后将来源复制到目的地。复制文件

    -g:自行设置所属的组;

    -m:自行设置权限,而不是默认的rwxr-xr-x

    -o:自行设置所有者

    -p:以来源文件的修改时间作为相应的目的地的文件属性

    %pre %post %pretun %postun 用法

    rpm提供了一种信号机制:不同的操作会返回不同的信息,并放到默认变量$1中

    0代表卸载、1代表安装、2代表升级

    if [“$1” = “0” ] ;then

    comond

    fi

    用于判断rpm的动作

    2.3 典型的spec文件案例:

    Name: xywy-varnish 
    Version: 4.1.0 
    Release: 1%{?dist}
    Summary: varnish rpm package
    Group: System environment/Daemons
    License: GPL
    URL: https://www.varnish-cache.org/
    Source: /home/fuzj/rpmbuild/SOURCES/varnish-4.1.0.tar.gz 
    BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
    BuildRequires: pcre pcre-devel python-docutils
    Requires: pcre pcre-devel python-docutils
    %description
    %prep
    %setup -q
    %build
    ./configure --prefix=/usr/local/xywy/varnish --enable-dependency-tracking --enable-debuggin-symbols --enable-developer-warnigs
    make %{?_smp_mflags}
    %install
    rm -rf %{buildroot}
    make install DESTDIR=%{buildroot}
    mkdir -p %{buildroot}/usr/local/xywy/varnish/etc
    install /home/fuzj/rpmbuild/SOURCES/default.vcl %{buildroot}/usr/local/xywy/varnish/etc

    %clean
    rm -rf %{buildroot
    %files
    %defattr(-,www,www,-)
    /usr/local/xywy/varnish/bin
    /usr/local/xywy/varnish/sbin
    /usr/local/xywy/varnish/include
    /usr/local/xywy/varnish/lib
    /usr/local/xywy/varnish/share
    /usr/local/xywy/varnish/var
    /usr/local/xywy/varnish/etc
    %changelog

    3.技巧:
    1)如果要避免生成debuginfo包:这个是默认会生成的rpm包。则可以使用下面的命令
    echo '%debug_package %{nil}' >> ~/.rpmmacros

    2)配置 RPM 在构建时使用新的目录结构,而不是默认的目录结构:
    echo "%_topdir $HOME/rpmbuild" > ~/.rpmmacros

    4.使用FPM制作RPM包
    1)安装:

    yum -y install ruby rubygems ruby-devel 安装ruby 和gem

    gem install fpm 安装fpm工具

    2)准备编译安装好的源码包

    /usr/local/libiconv

    3)打包:

    fpm -f -s dir -t rpm -n beyond-libiconv --epoch=0 -v '1.14' -C /usr/local --iteration 1.el6 ./libiconv-1.14

    参数解释

    -f 强制输出,如果文件已存在,将会覆盖源文件

    -s 指定源文件为目录 dir

    -t 指定制作的包类型(rpm,deb solaris etc)

    -n 指定制作的包名

    -- epoch 指定时间戳

    -v 指定软件版本

    -C 指定软件安装的目录

    --iteration 指定软件的适用平台

    ./libiconv-1.14 本次打包的文件

    附加参数:

    -e 可以在打包之前编译 spec文件

    -d 指定依赖的软件包 用法 –d ‘Package’ 或 –d ‘Package > version’

    --description 软件包描述

    -p 生成的package文件输出位置

    --url 说明软件包的url

    --post-install :软件包安装完成之后所要运行的脚本;和”--after-install” 意思一样

    --pre-install :软件包安装完成之前所要运行的脚本;和”--before-install” 意思一样

    --post-uninstall :软件包卸载完成之后所要运行的脚本;和”--after-remove”意思一样

    --pre-uninstall:软件包卸载完成之前所要运行的脚本;和”--before-remove”意思一样

    fpm打包php案例:

    fpm -f -s dir -t rpm -n beyond-php --epoch=0 -v '5.2.14' -C /usr/local/ -p ./ --iteration 1.el6 -d 'beyond-libiconv' -d 'beyond-libmcrypt' -d 'beyond-mcrypt' -d 'beyond-mhash' -d 'libxml2' -d 'libxml2-devel' -d 'zlib' -d 'zlib-devel' -d 'libpng' -d 'libpng-devel' -d 'freetype' -d 'freetype-devel' -d 'autoconf' -d 'gd' -d 'gd-devel' -d 'libjpeg' -d 'libjpeg-devel' -d 'curl' -d 'curl-devel' -d 'mysql-devel' -d 'openssl' -d 'openssl-devel' -d 'openldap-devel' -d 'libtool-ltdl' -d 'libtool-ltdl-devel' --url http://sa.beyond.com/source/php-5.2.14.tar.gz --license GPL --post-install ./preinstall.sh /usr/local/php

    1.两种rpm包

    用rpm打包,将会产生两种rpm包,一是源码包(xxx.src.rpm),一是binary包(xxx.rpm)。源码包可用于开源软件发布源码,一般包含xxx.spec文件和xxx.tar.gz文件;binary包用于直接软件安装,包含已完成编译的可执行文件以及相关配置文件等:

    复制代码
    # rpm -qlp ../SRPMS/hello-0.1-1.src.rpm 
    hello-0.1-1.spec
    hello-0.1-1.tar.gz
    
    # rpm -qlp ../RPMS/x86_64/hello-0.1-1.x86_64.rpm 
    /bin/hello
    /usr/share/doc/packages/hello
    /usr/share/doc/packages/hello/README
    复制代码

     2.打包目录

    从.tar.gz等格式的源码文件,到.rpm文件,需要经过编译过程,为此rpm提供了专门的目录进行打包:

    • SOURCES目录:存放.tar.gz源码文件
    • SPECS目录:存放.spec文件
    • SRPMS目录:存放生成的xxx.src.rpm文件
    • BUILD目录:存放解压后的源码文件或其他中间的临时文件
    • RPMS目录:存放生成的xxx.rpm文件

    对于suse,以上目录在/usr/src/packages路径下,对于RedHat,以上目录在/usr/src/redhat路径下。

     3.spec文件

    rpm包制作过程中最主要一步就是编写spec文件,spec文件用于提供软件相关描述以及如何编译、安装等信息,以下是一个spec文件示例:

    复制代码
    Summary: rpm hello world.
    Name: hello
    Version: 0.1
    Source: $RPM_SOURCE_DIR/hello-0.1-1.tar.gz
    Release: 1
    Vendor: lx
    License: Share
    Group: Application/test
    
    %description
    print hello
    
    %prep
    rm -rf $RPM_BUILD_DIR/hello-0.1-1
    zcat $RPM_SOURCE_DIR/hello-0.1-1.tar.gz | tar xvf -
    
    %build
    cd $RPM_BUILD_DIR/hello
    make
    
    %install
    cd $RPM_BUILD_DIR/hello
    make install
    
    %files
    %doc $RPM_BUILD_DIR/hello/README
    /bin/hello
    复制代码

    以上开头一段用于描述软件包相关信息,除了Summary/Name/Version/Source/Release/Vonder/License/Group外还有其他可选域,以上所列除Source外其他为必选域,建议在spec中提供Source信息,生成.src.rpm时软件包由Source提供的路径获取,否则.src.rpm中不包含.tar.gz源码包。

     后面%xx为spec文件的宏定义,在/usr/lib/rpm/macros文件找到相关定义,最重要的是以下几个部分:

    • %prep:编译前的准备部分,一般为删除之前的中间文件(BUILD目录),解压缩源码文件
    • %build:完成make编译部分,如果源码中提供了Makefile文件,就是一条make命令
    • %install:完成安装部分,如果源码中提供了Makefile文件,就是一条make install命令
    • %files:列出软件被安装后,目标机器上由该文件新建的文件,包括可执行文件、配置文件、man文件等

     4.生成目标文件

    .tar.gz文件放到SOURCES目录下,.spec文件编辑完成并放到SPECS目录下,这些完成后我们就可以打包生成.src.rpm文件和.rpm文件了:

    # rpmbuild -ba hello-0.1-1.spec

    以上rpmbuild命令用到 -ba 选项,表示既生成.src.rpm文件,又生成.rpm文件。以上命令执行后,我们来看各打包目录下生成的文件:

    复制代码

    /usr/src/packages # ll *
    BUILD:
    drwxr-xr-x 2 root root 4096 04-13 20:49 hello

    RPMS:
    drwxrwxrwt 2 root root 4096 04-13 20:49 x86_64

    SOURCES:
    -rw-r--r-- 1 root root 346 04-13 00:42 hello-0.1-1.tar.gz

    SPECS:
    -rw-r--r-- 1 root root 411 04-13 22:46 hello-0.1-1.spec

    SRPMS:
    -rw-r--r-- 1 root root 2076 04-13 20:49 hello-0.1-1.src.rpm

    复制代码

    RPMS的x86_64目录下:

    /usr/src/packages # ll RPMS/x86_64/
    -rw-r--r-- 1 root root 5102 04-13 20:49 hello-0.1-1.x86_64.rpm

     5.rpm解包

    rpm2cpio xxx.rpm | cpio -div

    方法1:使用rpmbuild来制作rpm包

    方法2:使用fpm来制作rpm包

    参考:http://www.tuicool.com/articles/Nj6nau

    写spec文件

    
    

         spec文件里有软件的版本,build,厂商拉。。。一堆属性信息。把头填好了,就写SPEC脚本了,就是一堆%pre, %build等等。以%开头的地方。我的spec如下

    
    
    Ruby代码  收藏代码
    1. Summary:example  
    2. Name:new  
    3. Version:0.1  
    4. Release:4  
    5. Group:Application/User  
    6. License:Share  
    7. Packager:dj  
    8. BuildRoot:%{_tmppath}/%{name}-%{version}-%{release}-root  
    9. Prefix:%{_prefix}  
    10. %description  
    11. #rpmtest example  
    12. %define userpath /usr/local/test/  
    13. %changlog  
    14. *Oct 25 2010  
    15. -build for the first time.  
    16. %prep  
    17. cp -r /usr/src/redhat/test/ /usr/src/redhat/SOURCES/  
    18. %build  
    19. %install  
    20. rm -rf $RPM_BUILD_ROOT  
    21. mkdir -p $RPM_BUILD_ROOT%userpath  
    22. cp -r /usr/src/redhat/SOURCES/. $RPM_BUILD_ROOT%userpath  
    23. %clean  
    24. rm -rf $RPM_BUILD_ROOT  
    25. %files  
    26. %defattr(-,root,root)  
    27. %{userpath}  
    
    
    
    
    

       

    
    

    解释几个容易迷惑的地方

    
    

    1) BuildRoot

    
    
    
    
    

    这是个临时的目录,制作安装包的时候用来测试的,定义好以后,后面的RPM_BUILD_ROOT 就指这个目录。执行install的时候了(当然由你自己把安装的动作放到这里的),会把文件安装到这个目录下面。所以在clean的时候了,又把下面的东西给删除了。如果没有它,那制作安装包的过程会把文件安装的真实环境里。

    
    
    
    
    

    2) %files
    这个文件列表起一个check的作用,表示我要装这些文件,看看rpm包你到底有没有安装。所以有时候会出现 installed (but unpackaged) file(s) found 的错误。表示你的files列表不对。

    
    
    
    
    

    3) 执行安装的时候文件安装到哪里去了?

    
    

    安装以后可以通过命令 rpm -ql  name 来查询这个包安装的路径。真是的路径就是RPM_BUILD_ROOT后面的%userpath

    
    
    
    
    

    3 执行rpmbuild建包

    
    

    做好包以后使用命令

    
    

    rpmbuild -bb new.spec

    
    

    根据spec脚本,执行建包过程。这个命令是构建二进制包,如果还需要保留源码那就是要用选项 -ba了。建好的rpm包放在这个目录下 Wrote: /usr/src/redhat/RPMS/x86_64/new-0.1-4.x86_64.rpm

     
  • 相关阅读:
    The Levy Flight
    Congestion and Flow Control at the Bundle Layer
    Fragmentation & Reassembly
    six classes of services in delay tolerant networks
    javascript的with表示什么?
    js定时器和计时器
    document.getElementById与getElementByName的区别
    MySQL查询时区分大小写的方法,查询字母出现中文的解决方法
    JavaScript的格式
    地址栏中传递中文参数
  • 原文地址:https://www.cnblogs.com/klb561/p/9271307.html
Copyright © 2011-2022 走看看