rpm 神器第二篇-multipkg 高阶用法介绍与实战

简介: 前言 前一篇文章中介绍了 multipkg 的安装和基本用法,这两天又结合之前的例子,整理了一篇类似于“实战系列”的文档,详细说明了 rpm 中的一些细节配置在multipkg中怎么写,以便读者能通过multipkg实现rpm/spec的高阶功能;另外,晚上总结了最近和以前的几个思路,给multi

前言


前一篇文章中介绍了 multipkg 的安装和基本用法,这两天又结合之前的例子,整理了一篇类似于“实战系列”的文档,

详细说明了 rpm 中的一些细节配置在multipkg中怎么写,以便读者能通过multipkg实现rpm/spec的高阶功能;另外,

晚上总结了最近和以前的几个思路,给multipkg加了一些功能,还未合并到作者的master分支,需要使用的同学可以直接从我

的仓库来获取:

git clone https://github.com/duanjigang1983/multipkg.git

cd multipkg

git checkout duanjigang1983

即可。

另外,examples/tskeeper 是我新加到其中的一个例子,tskeeper 的index.yaml详细展示了multipkg的配置方法,读者可以参考其写法(源代码是大概10年前

写的,如果有丑陋的地方,请包涵,因为我们的目的是为了展示multipkg的用法,并不是例子代码本身)。

下面,我们结合几个用法展开本文的内容:

rpm 安装空目录


为了能在 rpm 包中自带一个空目录,你需要在 spec 文件中通过这样的语法:

%dir dirname

告知 rpmbuild 这个目录需要保留在rpm文件中,而在multipkg中,spec 文件被封装起来了,如果要在rpm中自带空目录, 该怎么办呢?

查看源代码可以知道,在 multipkg 中,是通过每个目录中的 “.keep”文件来实现空目录保留的。比如:

root/
├── etc
│   ├── pkgaudit.conf
│   └── test.conf
├── usr
│   └── local
│       └── pkgaudit
│           ├── data
│           │   └── readme.txt
│           └── log
│               └── readme
└── var
目录 var 是一个空目录,直接:
multipkg .
编译得到的 rpm 文件通过
rpm -qpl xxx.rpm
命令看到的输出列表中,不包含 "/var"这个目录,如果 :

touch root/var/.keep

后,再次 multipkg 生成 rpm后,就能看到这个目录。

这个功能在multipkg的源码在文件 multipkg/source/lib/Seco/Multipkg.pm 中:

921     if ( -d _ ) {
 922       print $f $rpmattr . "\%dir /$_\n" if ( -e "$path/.keep" );
 923     }
 924     else {
 925       print $f $rpmattr . "/$_\n";
 926     }
 927   }
 928
如果是一个目录,并且其中包含了 ".keep "文件,就增加 “%dir” 语法到 spec 文件中。

读者可以参考我的git fork出来multipkg的例子(branch:duanjigang1983):

ls examples/tskeeper/root/usr/local/tskeeper/ -a
.  ..  .keep
首先,你可以删除 .keep 文件后生成 rpm 包,然后 rpm -qpl xxx.rpm 查看,rpm 包中是否有该目录,应该是没有的。

然后再touch 上.keep文件,编译rpm,进行查看验证。

requires 依赖等


依赖包的问题,直接在 index.yaml中编写就行,比如:

 arch: noarch
    provides:
        - Seco::Multipkg
        - perl-seco-class
        - perl-seco-cpan
    requires:
        - perl-YAML-Syck
        - subversion-perl
        - perl-Git
        - perl-Error
这样的写法,当然 conflicts,provides,requires 和 obsoletes 都支持如此写法。
configfiles 和 docfiles

configfiles 在 multipkg 中已经有支持,只不过原作者并未提供例子,在对代码进行分析后,我们得到了配置文件的书写语法。

如果在index.yaml中不添加files:这一项的话,所有安装的文件,multipkg都会把其添加到files列表中,默认属性是 :

%default(-,root,root)
比如,一个工程中,multipkg生成的 spec 文件如下:

%files
%defattr(-,root,root)
/usr/local/pkgaudit/log/readme
/usr/local/pkgaudit/data/readme.txt
/etc/pkgaudit.conf

/etc/test.conf
/etc/service/pkgaudit/run
/etc/service/pkgaudit/log/run
%dir /var
这时,/etc/test.conf 和 /etc/pkgaudit.conf 并不是conf 文件,因此通过:

rpm -qp xxx.rpm --configfiles
并不能看到任何配置文件输出。

这时,如果要把 某个文件加入到配置文件列表中,就需要在 index.yaml 中增加 files: 项了,格式如下( 仍以 tskeeper 为例):

 requires: ## tskeeper requires 'procps' and daemontools to be installed firstly
    - procps
    - daemontools
  provides:  ### The package 'tskeeper' will provide something named as 'tskeeper-examples' and 'cmesoft-tskeeper'
    - tskeeper-examples
    - cmesoft-tskeeper
  conflicts: ### sorry, i am conflicted with some rpms such as 'other-task-keeper' and 'all-task-keeper',
    - other-task-keeper
    - all-task-keeper
  obsoletes: ## when u want to install old-tskeeper with 'yum install old-tskeeper', you will get me -'tkeeper' ^_^
    - old-tskeeper
    - taskeeper
  files:
    - "/etc/test_conf1.conf":  ##just set attributes of this file, but not a configfile
        group: "root"
        perm:  "0666"
        owner: "root"
    - "/etc/test_conf2.conf":
        group: "root"
        perm: "0777"
        owner: "nobody"
        config: "no" ## no matter what this value will be, 'config' tells multipkg 'please set me as a config file'
    - "/etc/proclist.ini":
        group: "root"
        perm: "0666"
        owner: "root"
        config: "yes" ## no matter what this value will be, 'config' tells multipkg 'please set me as a config file'
    - "/var/doc/tskeeper":
        group: "root"
        perm: "0444"
        owner: "root"
        doc: "xxoo"  ## yes, 'doc' is a newlly-added feature for multipkg
生成 rpm 文件后,可以看到 configfiles 为:

/etc/proclist.ini
/etc/test_conf2.conf
docfiles 为:

/var/doc/tskeeper
说明:docfiles这个属性支持属于新增加到multipkg中的功能,作者master分支中尚不支持。

接着,配置文件的 perm, owner 和 group 在安装后会如配置中填写的一样,如果你只是想设置某个文件的属性,而不想将其配置为config(也就是说在

包升级或者卸载时老的配置文件会保留),你可以删除 config: "yes"这项(注意 config:"xx",xx可以是任何值,他只是个标志,并无特殊意义),

比如,去除 /etc/test_conf2.conf 的 config: "yes"项后,

再次通过 --configfiles 查看rpm包时,就看不到 /etc/test_conf2.conf这个配置文件了。但是,有一点要注意,attributes 还会继续生效。

另外,config 类型的文件已经默认有了 noreplace 属性了,不需要再在spec中或者 index.yaml 文件中添加。

configfiles 更新原则


配置文件更新的原则是:

(1) 升级/安装一个package 时,如果老的配置文件不存在或者无修改,则生成新的配置文件,或者替换老的配置文件。

(2) 升级时,如果老的配置文件有改动,而新包中的配置文件和老包中自带的配置一样的话,使用老的修改了的配置文件,不安装新包中的配置文件,

而且 rpm -qf  查询时,老的配置文件属于新版本的rpm包。

(3) 升级时,如果配置文件有更新,而老的配置文件又被修改了,那么老的修改的配置文件会被更名为 “配置文件名称.save”以做保存。

(4)卸载时,配置文件保存为 “配置文件名.save”,不做删除。

输出或者定制 spec 文件


 multipkg 生成 rpm 并不需要使用者编写spec文件,但是其自身还是依赖spec文件的,所以,在build rpm 的过程中,必然有 spec文件生成。

我们可以看下 multipkg 的帮助:

-f, --force          Force build on sanity-check failure
-h, --help           Display this help
-k, --keep-files     Keep files after build
-p, --platform       Include this platform
-s, --set            List of variables to set
-t, --testbuild      When building from a work dir, not source control
-v, --verbose        Be verbose

其中 -v -k 就能看到spec文件,比如:

# multipkg -v -k examples/tskeeper
可以看到:

INFO: RUNNING: INSTALLROOT=/tmp/vCfqjg2WVR/install rpmbuild -bb --define '_topdir /tmp/vCfqjg2WVR/rpm/rpmtop' --buildroot /tmp/vCfqjg2WVR/install /tmp/vCfqjg2WVR/spec
然后自己打开:

/tmp/vCfqjg2WVR/spec
这个文件,你一定会恍然大悟的。注意这个路径是随机的,应该参考命令行输出去获取。

另外,multipkg 在build 时,其实是基于一个spec模版文件来生成每个package的spec文件的,这个模版在

源码中的路径为:

root/usr/share/multipkg/templates/spec.template
看了之后,你一定会对 multipkg的原理又有更深的了解了。

请留意本版本中本人对spec.template的修改(description, group, packager 等字段)

关于rpm文件的description属性(新增加功能)


在rpm中,读者可以通过大量文本内容来描述他的rpm包,但是在 multipkg中始终还未支持这个属性的配置,反而采取了较为简单的

作法,配置 description的内容为summary的内容,这个通过spec.template中的:

%description
%summary%
看到,所以,你通过 multipkg 制作的rpm,在 -qpi 查看时,总能看到 summary 和 description 是相同的。

虽然 Desc 不是 rpm 的核心,但是总是影响雅观的,所以,我在multipkg中增加了 setdesc 函数,使得用户在index.yaml中

既可以配置其为一个 字符串,也可以配置其值为一个命令的执行结果(不知道这个功能会不会被人诟病)。

具体说明是:

A: 字符串


 配置

description:"this is a description"
你通过

rpm -qpi xxx.rpm
看到的 description 就是 "this is a description"这个内容。

B: 配置为命令


配置为命令时,rpm -qpi xx.rpm 看到的 desc 的内容就是命令执行的结果,一般建议配置为打印desc文件的内容,比如你可以写:

description:"cmd:cat /source/desc.txt"
注意格式为:

[description:"命令关键字(cmd):命令内容"]

如果没有"cmd:"开头,multipkg 就会认为是情况A(字符串)。

建议:在实际中不要配置description为乱七八糟的内容,比如:

description:"cmd:hostname,ps aux;"

并没啥意思,因为 multipkg 会把 build 机器的 hostname 和 ps aux 命令的结果作为desc 的内容。

另外,如果有文件操作,参数如果是相对目录,那么 默认 当前目录是你的工程的根目录,这个一定要注意。

比如:

# multipkg  /root/multipkg/examples/tskeeper

tskeepr 的 description 为:

description: 'cmd:cat source/desc.txt;hostname'
build rpm包时,

"cat source/desc.txt"
会在

/root/multipkg/examples/tskeeper
目录下去找

"source/desc.txt"
文件。

后记


关于 multipkg 的使用配置和一些功能细节就介绍到这里,如果您还有更好的建议或者使用,开发的问题,欢迎与我联系: cmesoft@126.com。关于rpm/yum的基础知识,以及rpm管理平台的建设等问题和专业知识可以参考《Linux 软件管理平台设计与实现》一书。
相关文章
|
7月前
常用工具方法--持续更新
常用工具方法--持续更新
45 0
|
机器人 测试技术 Android开发
【第二篇】XiaoZaiMultiAutoAiDevices之基本使用
从一个框架,延伸各项知识点,补补基础,挺好~
143 0
|
IDE Ubuntu 开发工具
Python入门系列第一章--第一节:环境搭建
Python入门系列第一章--第一节:环境搭建
131 0
Python入门系列第一章--第一节:环境搭建
封装简介 | Python从入门到精通:高阶篇之二十六
本节重点介绍了封装的定义以及封装的总体思路,隐藏属性名,增加getter和setter方法,使用setter方法设置属性,使用getter方法获取属性。
封装简介 | Python从入门到精通:高阶篇之二十六
|
Python 程序员
语法学习 | python从入门到精通:入门篇之四
本节将学习一些Python的的基本语法,包括变量、标识符、字面量等内容。
10251 0
语法学习 | python从入门到精通:入门篇之四
|
存储 开发者 Python
文件的写入 | Python从入门到精通:高阶篇之四十九
可以使用write()来向文件中写入内容,如果操作的是一个文本文件的话,则write()需要传递一个字符串作为参数。该方法可以分多次向文件中写入内容,写入完成以后,该方法会返回写入的字符的个数。
文件的写入  | Python从入门到精通:高阶篇之四十九
|
缓存 Python
初识包 | Python从入门到精通:高阶篇之三十八
本节重点介绍了包的概念以及用法优势,将相关的模块放在一个包中,方便管理并且在引用的时候也可以根据需要去引用。
初识包 | Python从入门到精通:高阶篇之三十八
|
索引 Python
异常简介 | Python从入门到精通:高阶篇之四十
本节我们介绍了程序运行过程中异常的产生以及简单的处理方式(try语句)。
异常简介 | Python从入门到精通:高阶篇之四十
|
关系型数据库 Python
继承简介 | Python从入门到精通:高阶篇之二十九
本节重点讲了继承是面向对象的三大特性之一,以及子类继承父类的用法。
继承简介 | Python从入门到精通:高阶篇之二十九