rpm打包学习

1.RPM目录结构

- rpmbuild
  - SOURCES    源码、图标等文件
  - SPECS      用于管理rpm制作进程的spec文件
  - BUILD      解压后的文件
  - RPMS       由rpmbuild制作好的二进制包
  - SRPMS      由rpmbuild制作好的源码包

2.spec文件综述

  • spec文件有什么用?
  • spec文件有两个用途:构建打包。构建即将源码转换为构建工件(java构建工具一般为Ant, Maven, Gradle; C语言构建工具为makefile)。打包即确定需要安装在目标机器上的构建产物。

注意:#字符表示注释,但需要避免注释宏(以 % 开头),因为它们会首先被替换展开。使用 %% 注释宏。另外,还要避免在脚本命令的相同行中使用行内注释。

%{name}%{version}%{release} 代表 Name, Version 和 Release 这三个标签。只要更改标签,宏就会使用新值。

spec文件主要标签:

  1. Name: 软件包名,应与 SPEC 文件名一致。

  2. Version: 版本号。

  3. Release: 发行编号,初始值为 1%{?dist} ,每次制作新包时,递增该数字。

    • 什么是 1%{?dist} : 如果%{dist}未定义返回1,否则返回1%{dist},
    • 用法:
      1. if判断:
        if 0%{?flag}; then
            foo
        fi
        
        如果%{flag}被定义了,条件语句为:0%{flag},执行if block; 反之,条件语句为:0, 不执行if block。
        注意:%{?flag}前必须加0,否则如果%{?flag}未定义,if语句停止执行并退出。
      2. %{?flag: ...}:如果%{flag}被定义,则展开"..."部分;
  4. Patch0: 用于源码的补丁名称。如果需要在源码包解压后对一些代码做修改,应该修改代码并使用 diff 命令生成 patch 文件,然后放在 ~/rpmbuild/SOURCES 目录下。一个 Patch 应该只做一种修改,所以可能会包含多个 patch 文件。

  5. BuildRoot: 在 %install 阶段(%build 阶段后)文件需要安装至此位置。默认情况下,根目录为 %{_topdir}/BUILDROOT/

  6. %description: 程序的详细/多行描述。每行必须小于等于 80 个字符。

  7. %prep: 打包准备阶段执行一些命令(如,解压源码包,打补丁等),以便开始编译。

  8. %build: 包含构建阶段执行的命令,构建完成后便开始后续安装。

  9. %install: 包含安装阶段执行的命令。命令将文件从 %{_builddir} 目录安装至 %{buildroot} 目录。可以使用 $RPM_BUILD_ROOT 代替 %{buildroot},两者都可以使用。

    术语:

    • %{_builddir}(即"build目录"),与 %{buildroot}(即"build root目录")是不同的目录。在%{_builddir}中进行编译,并将需要打包的文件从%{_builddir}中复制到%{buildroot}中。
    • %install阶段的命令不会在用户安装RPM包时执行,此阶段只在打包时执行。
      一般在%install阶段执行make install之类的命令。%make_install命令等同于 DESTDIR=%{buildroot} ,该命令会将文件安装到%{buildroot}目录中。如果程序不支持 DESTDIR ,可手动执行安装:需要在%{buildroot}下创建必要的目录,并从%{_builddir}复制文件至%{buildroot}目录。
  10. %clean: 清理安装目录。一般只包含:rm -rf %{buildroot}

  11. %files: %files指令列出需要安装的文件和目录。

    • %defattr 用于设置默认文件权限,一般在%files开头设置。格式为:

      %defattr(<文件权限>, <用户>, <用户组>, <目录权限>)
      

      常规用法为:

      %defattr(-, user, group, -) 
      
    • 必须在 %files 部分列出该软件所拥有的所有文件,注意不要使用如 /usr/bin/ 的硬编码,尽量使用宏代替目录名。

    • 如果路径以"/"开头(或从宏扩展),则认为文件在%{buildroot}目录中。否则,默认文件在当前目录中。
      【问题:如果软件包仅安装一个文件,那么该文件会安装在哪里?】
      【答:必须有一个路径】

    • 若要软件包不受上游改动影响,可使用通配符匹配所有文件。
      【问题:不受上游改动影响是什么意思?】
      注意:%{somedir}/*不会声明软件包拥有%{somedir}目录,而只包含其中的文件。如果列出一个目录,则该软件包拥有整个目录,以及该目录内所有的文件和子目录,因此要小心处理可能和其他软件共享的目录。

    • 如果存在以下情况,可能引发错误:

      • 通配符未匹配任何文件或目录
      • 文件或目录被多次列出
      • %{buildroot}中有文件未列出(空文件目录不会报错)
      • 使用通配符来列出全部文件时,可使用 %exclude 来排除文件。注意如果未匹配到任何文件也会造成失败。

3. %files指令

%files列表包括多种指令,主要用于:

  • 识别文档和配置文件
  • 确定文件有正确的权限和拥有组
  • 设置哪些文件需要在打包验证时进行校验
  • 精简语法

两个%files指令可同时作用于同一个文件,例如:%foo %bar baz

I 文件相关指令

RPM需要根据文件类型分别处理不同类型的文件,然而,rpm并没有自动识别文件类型的功能。因此,需要由打包者适当的对不同类型的文件进行标识。
注意:并非所有文件都需要被标识,在大多数包中,大多数文件都不需要被标识。

  1. %doc 指令:
    rpm会跟踪其数据库中的文档文件,以便用户查找已安装包信息。
    此外,rpm可在安装期间创建包的文档目录,并将文档复制其中。添加该步骤方法如下:
    %doc README
    %doc /usr/local/foo/README
    
    build期间,README 文件位于顶级目录;软件包install完成后,rpm将在软件包同名的文档目录(即<software>-<version>-<release>)创建目录,并将 README 文件拷贝其中。新创建的目录和 README 文件将在rpm数据库被作为文档进行标识。默认的文档目录是/usr/doc,可在rpmrc文件中更改。
  2. %config 指令:用于标识文件作为配置文件。(只能一个配置文件)
  3. %attr 指令:用于设置文件权限。例:
    %attr(<file_mode>, <user>, <group>) filename 
    
  4. %defattr 指令: 用于设置文件默认权限,一般写在%files头部。例:
    %defattr(<file_mode>, <user>, <group>, <dir_mode>)
    
  5. %ghost to be continue...
  6. %verify to be continue...

II 目录相关指令

  1. %docdir 指令:向文档目录列表添加目录。rpm的%docdir列表默的认目录有:/usr/doc, /usr/info, /usr/main。例:

    %docfir /usr/test ,
    

    任何/usr/test目录下的文件都会自动被标识为文档文件。

  2. %dir 指令:之前提到,如果在%files下列出文件夹,则该文件夹下的所有文件或子文件夹都会被打包到软件包中。%dir指令可设置rpm只打包自身,而忽略其中的文件或子文件夹。

  3. -f <file>:从<file>中读取%files列表。


Tips

  1. shell脚本错误 Syntax error near unexpected token `fi`:缺少 then
  2. spec文件内的标签必须有值,标签前不能有空格;
  3. spec文件必须要有%description
  4. spec文件的当前目录为/BUILD
  5. %{buildroot}%install阶段,/BUILDROOT下自动创建的子目录/name-version-release
  6. %{buildroot}内的所有文件都必须在%files中列出,空目录可不必列出
  7. /BUILDROOT目录会在%install阶段自动创建

代码参考

package.sh:

CUR_DIR=$(cd `dirname $0`; pwd)

if [ -d ${CUR_DIR}/rpmbuild ]; then
    rm -rf ${CUR_DIR}/rpmbuild
fi
mkdir -p ${CUR_DIR}/rpmbuild
mkdir -p ${CUR_DIR}/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
cp  ${CUR_DIR}/*.spec   ${CUR_DIR}/rpmbuild/SPECS/
rpmbuild --define "_topdir ${CUR_DIR}/rpmbuild" -bb ${CUR_DIR}/rpmbuild/SPECS/web.spec

web.spec:

Name:           web
Version:        1.0.0
Release:        1%{?dist}
Summary:        test
License:        GPL
URL:            http://gitlabsec.huawei.com/h00416865/web

%description

%define PROJECT_ROOT %{_builddir}/../../..

%prep

%build
echo "begin to mvn install..."
cd %{PROJECT_ROOT}/web_console
mvn clean install

%install
rm  -rf    %{buildroot}
mkdir   -p  %{buildroot}/opt/weiee
mkdir   -p  %{_builddir}/webapp
cp  -r  %{PROJECT_ROOT}/web_console/target/*.war    %{_builddir}
unzip   -oq %{_builddir}/*.war  -d  %{_builddir}/webapp
cp  -r  %{_builddir}/webapp     %{buildroot}/opt/weiee

%files
%defattr(-,root,root,-)
/opt/weiee/

%post

%clean
rm -rf %{buildroot}

%changelog

参考文章

http://ftp.rpm.org/max-rpm/index.html
How to create an RPM package/zh-cn

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 117,087评论 15 132
  • 引言 Go 语言这两年在语言排行榜上的上升势头非常猛,Go 语言虽然是静态编译型语言,但是它却拥有脚本化的语法,支...
    一缕殇流化隐半边冰霜阅读 28,386评论 11 89
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 153,652评论 23 674
  • 此篇文章是针对Mac版本的设置 1.下载mysql, 下载的地址:http://dev.mysql.com/d...
    liuian1946阅读 48评论 0 1
  • 有一天,我们都走了,而你还在那里, 你会为我们镌写一纸书文吗? 可能我们都只是过客,而你却是这个世界的见证人! 我...
    来自书本的书虫阅读 34评论 0 0