忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 70048 | 回复: 51

Linux平台软件管理系统设计与规划-基础篇(1)-RPM文件认识与格式剖析 [复制链接]

论坛徽章:
0
发表于 2012-11-14 23:03 |显示全部楼层
本帖最后由 duanjigang 于 2012-11-17 23:03 编辑

转载请保留作者信息和来自CU的原站
2012-11-17: 更新至27楼
################

在论坛有大半年时间没写文章了,今天“发表帖子”都不知道怎么写了。看看这个荒芜的板块,顿时觉得有些内疚,就跟自家的自留地好久没有经管一样,呵呵,忙完了一阵子,终于有空来
总结下了,旨在作为自己工作总结,也为需要的同学提供点参考,

今年年初到现在这断断续续七八个月都在负责维护公司yum系统,进行RPM/YUM的日常支持,浑浑噩噩也学了不少东西,虽然不能对yum/rpm这些做到精通,但是也算是有所了解,于是在9月份,厚着脸皮去CU的架构师大会分享了一把,演讲标题是《Linux平台软件管理系统设计与规划》(可以从此下载PPT:http://bbs.chinaunix.net/thread-3771155-1-1.html)。其中洒洒扬扬对rpm/yum进行了介绍,高可用性/稳定的yum系统搭建进行了较为深入的分析,都是结合着在公司的工作内容讲的,最后第三部分还就软件包制作与命名管理规范就行了一些分享。总觉得架构师大会上一小时的时间太短,说不清好多东西,于是希望在线下进行一个系列的帖子总结和讨论,算是对演讲PPT的深入吧。废话不多,开始了。

论坛徽章:
0
发表于 2012-11-14 23:14 |显示全部楼层
本帖最后由 duanjigang 于 2012-11-14 23:20 编辑

看文章的标题和PPT的内容,很容易理解,要说的对象是RPM和YUM系统,鄙人不太喜欢那种太教材方式的介绍,喜欢从个人的最直观理解去阐述,叙说。呵呵,希望都能适应。

RPM文件

首先说说 RPM 文件,百度下RPM,可以看到英文名字是:RedHat Package Manager, 应该说是一个包管理方式,或者一个包管理工具。提到包管理,就赘述几句,什么是软件包呢?我的理解,最原始的包就是一堆需要运行的程序的集合,可能还需要加上一些配置文件,动态库之类,就构成了软件包。
你把自己写好的脚本或者C代码编译生成的二进制文件,加上依赖的某些so文件和conf文件,扔进一个目录,叫做execute,那么,我们就可以说excute是一个软件包了。。
有人可能说这怎么能叫软件包呢?仔细想想,它确实应该是一个软件包,它包含了要运行的应用需要的基本东西,执行程序,配置,依赖库等,只不过这个包看起来有些原始和过于简单而已。
    有了基本的软件包-一个目录中存放文件的集合,我们就会想着更高级别的软件包,比如对excute进行压缩,也是一个包,通过tar或者gzip得到tar.gz,rar,zip格式的文件,你就获得了一个较为高级的软件包了,它确实比较高级,因为它把程序和配置变成了一个单一的文件,这样就方便拷贝了,另外压缩文件的包方式,也节省了磁盘空间占用和网络数据传输的量。在我之前从事3年的单位,我们所在项目组的程序基本都是通过这种方式发布的,每次发布程序,都是把动态库,二进制程序和配置文件压缩成一个tgz文件,拷贝到需要运行的2000多台机器上,解压缩到指定目录下,然后直接运行即可。看的出,这种方式已经比较方便了。

论坛徽章:
0
发表于 2012-11-14 23:35 |显示全部楼层
本帖最后由 duanjigang 于 2012-11-15 07:06 编辑

有了tgz/rar/zip方式的包管理和存储方式就够了吗?可能对于某些小型应用确实够了,但是,日常工作中你应该会碰到如下一些问题:
(1):  想看这个软件包的信息,比如谁制作的,什么时候制作的,描述信息呢?
(2):  给软件包带上一些特殊功能,除了文件拷贝功能外,还要有配置文件生成,安装服务,执行命令等操作,压缩文件怎么用?
(3):  软件包版本升级时,通过压缩文件怎么做?
除了以上这3点,应该还有其他方面的问题,你应该都会遇到或者思考到。再思考下。。。压缩文件格式的软件包确实存在这些功能上的不足,能不能在文件压缩存储之外在能进行更多功能的实现和更多信息的存储呢?把这些都写入最终的包文件中?
   答案是肯定的,呵呵。
RPM 就是具有上面提到功能需求的一个包存储或者管理方式。当然还有其他方式的高级软件包格式,不过本文和后续的文章中只对RPM这种方式进行讨论。先来看看这中高级软件包的特点或者说功能吧:

(1): 压缩存储数据。(和tgz方式一样)
(2):   文件安装到指定路径(基本功能)。
(3):  配置文件产生。
(4):  系统服务注册
(5):  软件依赖检查。


除了(1)和(2),后面这三个功能,大概是压缩方式软件包都不具有的特性吧。

   压缩存储,这个是基本功能,比如我这里有个目录是5.2M,用它制作好的RPM只有2.4M.
   文件安装,这个同样是基本功能,运行命令:

  1.   rpm -qpl ./cmeguard-1.1.2-34.i386.rpm
  2. /etc/init.d/cmeguard
  3. /usr/local/cmeguard/bin/auto_update
  4. /usr/local/cmeguard/bin/cmeguard
  5. /usr/local/cmeguard/bin/cmesync
  6. /usr/local/cmeguard/bin/daemon
  7. /usr/local/cmeguard/bin/genfinger
  8. /usr/local/cmeguard/bin/run
  9. /usr/local/cmeguard/bin/sync_plug
  10. /usr/local/cmeguard/bin/sync_plug_back
  11. /usr/local/cmeguard/conf/cmeguard.conf
  12. /usr/local/cmeguard/conf/cmeproxy.conf
  13. /usr/local/cmeguard/conf/cmesync.conf
  14. /usr/local/cmeguard/conf/error.html
  15. /usr/local/cmeguard/conf/mime.types
  16. /usr/local/cmeguard/data
  17. /usr/local/cmeguard/db
  18. /usr/local/cmeguard/finger
  19. /usr/local/cmeguard/lib
  20. /usr/local/cmeguard/log
  21. /usr/local/cmeguard/pid
  22. /usr/local/cmeguard/tmp
复制代码
能够看到这么一大坨文件,这里看到的文件就是将来会安装的文件列表,如果你用默认安装命令
  1. rpm -ivh cmeguard-1.1.2-34.i386.rpm
复制代码
安装这个包的话,就会在你的系统上找到上面列表中对应的所有文件,而且最少是这些文件(因为安装时可能会产生新的文件,这个后面会说)。

然后是配置文件产生:配置文件即可以通过安装列表中的文件来生成,也可以通过安装过程中的脚本来生成。

服务注册:如果你用rpm安装过apache,mysql-server等常见软件的话,应该会知道,安装完,会对应在/etc/init.d/底下创建一个httpd或者mysqld的文件,这个文件按照
标准的自启动脚本格式书写的(参考chkconfig),当系统以对应的模式启动时,你安装的服务程序就会被运行起来。
举个例子:

  1. rpm --nosignature -qpl ./vsftpd-2.0.5-10.el5.i386.rpm  | grep init
  2. /etc/rc.d/init.d/vsftpd
复制代码
能够看到

  1. /etc/rc.d/init.d/vsftpd
复制代码
这个文件会被安装,然后你就可以通过

  1. service vsftpd start/stop/restart/status
复制代码
等方式来控制这个服务的起停了。

软件依赖检查: 我们开发的程序很少是单独运行的,大多数都会依赖其它软件,比如你开发的数据库处理程序可能需要 libmysql,网络报文处理程序需要libpcap这个包的支持,这时,为了保证你的软件安装后能正常运行,而且在安装时能够检查环境是否就绪,就可以通过软件依赖的方式来实现(当然,有人可能会问怎么实现这些呢,这个在后面的spec语法中会详细说明)。
还是举个例子,比如有个rpm叫:

  1. test_rpm-1.1.1-21.i386.rpm
复制代码
首先我们看下它require哪些咚咚:

  1. rpm -qp test_rpm-1.1.1-21.i386.rpm --requires
  2. test__require_pkg  
  3. ruby-libs  
  4. /bin/sh  
  5. /bin/sh  
  6. rpmlib(PayloadFilesHavePrefix) <= 4.0-1
  7. rpmlib(CompressedFileNames) <= 3.0.4-1
复制代码
能够看到它依赖了这些组件或者包。

然后尝试安装下:

  1. rpm -ivh test_rpm-1.1.1-21.i386.rpm           
  2. error: Failed dependencies:
  3.         test__require_pkg is needed by test_rpm-1.1.1-21.i386
复制代码
能够看到,系统缺少 test__requre_pkg 这个包,因此 test_rpm-1.1.1-21.i386.rpm
这个包是不能安装成功的,这样的逻辑确实是合理和应该的.虽然我们能够看到

  1. rpm -qa ruby-libs
  2. ruby-libs-1.8.5-5.el5_3.7
复制代码
这个包已经安装了,但是在依赖列表中,缺一不可,它们是与的关系。
好了,RPM 这五个特性,我们就说到这里。

论坛徽章:
0
发表于 2012-11-15 07:21 |显示全部楼层
本帖最后由 duanjigang 于 2012-11-15 07:29 编辑

再来少许赘言对上面起初提的问题进行回答: RPM 是怎样在压缩存储之外又能做到其它功能的呢,比如安装服务,执行某些命令,打印信息,发邮件,检查依赖包,还有升级时做版本检查。这些都怎么实现的?
   在此不做太细致说明,还是留待spec文件那节再说吧。
RPM有个功能就是对 scripts 的支持功能,除了文件压缩存储,它支持在安装软件或者卸载软件的过程中(确切点说,是这个过程的开始,进行和结束后这些不同时间点),执行一些命令,常用的有

  1. post install
  2. pre install
  3. post uninstall
  4. pre uninstall
复制代码
从字面意思就能看到其作用,也就是说能够在安装前,安装完,卸载前,卸载完执行某些脚本,这就为扩展包功能提供了极大的空间。
我们看一个例子:

  1. rpm -qp test_rpm-1.1.1-21.i386.rpm --scripts
  2. preinstall scriptlet (using /bin/sh):
  3. echo "pre install scripts by duanjigang"
  4. postinstall scriptlet (using /bin/sh):
  5. echo "post install scripts by duanjigang"
  6. preuninstall scriptlet (using /bin/sh):
  7. #!/bin/bash
  8. echo "pre uninstall by duanjigang"
  9. postuninstall scriptlet (using /bin/sh):
  10. #!/bin/bash
  11. echo "post uninstall by duanjigang"
复制代码
能够看到这个软件包有 5 个 scripts 在 RPM 中带着,分别在安装前后,卸载前后,build 这五个点执行,这样,你就可以通过这些 Scripts 来实现想要的功能了。
关于 scripts 在那些不同点执行,有什么效果,后面我会详述。

   还有就是 RPM 怎么做到版本的控制和变化?
通过这个信息

  1. rpm -qpi test_rpm-1.1.1-21.i386.rpm
  2. Name        : test_rpm                    
  3. Version     : 1.1.1                             
  4. Release     : 21                        
复制代码
能够看到 版本时1.1.1, Release 号是21,因此它的包名默认就是:
test_rpm-1.1.1-21
当version进行升级,或者 Release 号进行升级后,新版本的 RPM 就可以在老的版本上做版本升级了,而切 RPM 安装器会检查版本号,然后确定是否能够升级。
有时候,制作包时也会用 RPM 的 “Epoch” 这个字段来控制版本,可以称这个字段是一个神秘数字吧,他会加在版本的前面,用冒号隔开,比如:

  1. 99:1.1.1-21
复制代码
这样的一个版本字符串,和

  1. 1.2.3-xx
复制代码
来比较,前者始终比后者版本高,后者版本的包就没法升级前者了,当然这么做并不全是为了控制版本升级,主要目的还是做特殊标识的。
RPM 的基础介绍部分先到这里。:wink:

论坛徽章:
379
CU十二周年纪念徽章
日期:2014-01-04 22:46:58CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-03-13 15:38:15CU大牛徽章
日期:2013-03-13 15:38:52CU大牛徽章
日期:2013-03-14 14:08:55CU大牛徽章
日期:2013-04-17 11:17:19CU大牛徽章
日期:2013-04-17 11:17:32CU大牛徽章
日期:2013-04-17 11:17:37CU大牛徽章
日期:2013-04-17 11:17:42CU大牛徽章
日期:2013-04-17 11:17:47CU大牛徽章
日期:2013-04-17 11:17:52CU大牛徽章
日期:2013-04-17 11:17:56
发表于 2012-11-15 08:29 |显示全部楼层
感谢分享,坐板凳学习

论坛徽章:
4
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11IT运维版块每日发帖之星
日期:2016-08-11 06:20:00IT运维版块每日发帖之星
日期:2016-08-15 06:20:00
发表于 2012-11-15 09:28 |显示全部楼层
兰兰V5,感谢分享!

论坛徽章:
0
发表于 2012-11-15 09:40 |显示全部楼层
本帖最后由 duanjigang 于 2012-11-15 10:56 编辑

RPM 文件格式

做过网络程序开发或者数序wireshark (or tcpdump)的同学肯定都对报文文件比较熟悉,我们都知道,网络报文文件都有它固定的文件格式,或者我觉得叫协议更容易理解。
这些协议是人为定下来的,告知大家:我们这个文件前面多少比特写什么内容,中间哪个数据结构表示什么意思,后面那个字段又代表什么。。总之,通过这么一种通告的方式向众生告知,如果你要参与到这种格式的数据(或者文件)中来,就必须按照我说的格式(协议)去读写,只有这样,你才能够读取到正确的数据,或者写成一个正确格式的文件。

报文文件为大家熟知,我们就从报文文件的例子开始。下面是我用wireshark抓取的一个数据包,用wireshark 查看该文件,能够清晰看到按照报文文件协议解析后的数据包文件的各个字段:
链路层
IP层
TCP层
FTP层
每层的各个字段都能看到。
ftp.JPG

之所以 wireshark 能够展示出来报文的每个字段,因为它是去按照报文文件的协议进行解析的,对于 RPM 文件,原理也是一样的,知晓了文件的数据格式,然后去逐个解析,就能拿到你想要的信息,RPM 命令其中的大部分功能,也都是这样实现的。


下面,我们看看 RPM 的文件格式。
就像报文文件由 MAC层,IP层,TCP/UDP/ICMP层,HTTP/SNMP层这些信息块组成一样,一个 RPM 文件由一下几种数据块组成:

lead

signature

header

archive

在 一个 RPM 文件中,上面这四种数据元,会被包含一个或者多个,其中每个数据元中又有自己的数据格式,这样,一层层的存储协议,就构成了一个RPM文件。

论坛徽章:
4
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:28
发表于 2012-11-15 09:52 |显示全部楼层
获益良多呀

论坛徽章:
0
发表于 2012-11-15 10:59 |显示全部楼层
本帖最后由 duanjigang 于 2012-11-15 11:50 编辑

接着。

首先看 Lead 信息。

rpm-devel 这个包中 的文件 /usr/include/rpm/rpmlib.h  中 对 rpmlead
是如是定义的:

  1. unsigned char magic[4];
  2.     unsigned char major;
  3.     unsigned char minor;
  4.     short type;
  5.     short archnum;
  6.     char name[66];
  7.     short osnum;
  8.     short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
  9. /*@unused@*/ char reserved[16]; /*!< Pad to 96 bytes -- 8 byte aligned! */
复制代码
通过字面意思大概能看到几分意思,最起码这个结构体包含了包的名字,os 类型, arch数,包类型(二进制包还是源码包)。

前四个字节,magic,是表示这个文件是否是RPM文件的标识,file 命令和 rpm 命令都是靠这前四个字节来判断的
比如:

  1. file test-rpm-1.1.1-15.x86_64.rpm
  2. test-rpm-1.1.1-15.x86_64.rpm: RPM v3 bin i386 test-rpm-1.1.1-15
复制代码
基本上就是从 lead 中获取了主要信息输出的。
目前,这个magic 数组是 “edab eedb”,可以通过 ultraedit 打开一个RPM 文件 查看前四个字节,如图示:
ftp.JPG

接下来两个字节 major 和 minor 是标识 RPM 文件格式的版本的,这个和 TCP/IP 协议的版本一样,就像网络报文中的 version 大多为 4 和 6 一样。
RPM文件中能看到的大多数值都是  major = 3 minor = 0, 也就是 3.0 版本的 RPM 文件。
在上图中同样能看到。

下来是 RPM 文件的类型 type,0 是 二进制 RPM 文件,1 是源码二进制文件,标识了RPM中存的是二进制程序还是源码包。



下来的archnum 是用标识 包将要安装的架构信息的,1 标识i368,在最新的 rpm version 3.0 中看到的 这个字段在 x86_64, noarch 和 i386 中都是0,可能已经不用这个字段了,而是采用header来存储,这个后面再说。

66个字符的 name 是包的名字。
osnum 是标识 操作系统的, 1 标识是 Linux,2 是 IRIX,这些对应的常量定义能在文件 /usr/lib/rpm/rpmrc
中看到:

  1. os_canon:       Linux:  Linux   1   
  2. os_canon:       IRIX:   Irix    2   
  3. # This is wrong
  4. os_canon:       SunOS5: solaris 3
  5. os_canon:       SunOS4: SunOS   4   

  6. os_canon:      AmigaOS: AmigaOS 5
  7. os_canon:          AIX: AIX     5   
  8. os_canon:        HP-UX: hpux10  6
  9. os_canon:         OSF1: osf1    7   
  10. os_canon:       osf4.0: osf1    7   
  11. os_canon:       osf3.2: osf1    7   
  12. os_canon:      FreeBSD: FreeBSD 8
  13. os_canon:       SCO_SV: SCO_SV3.2v5.0.2  9
  14. os_canon:       IRIX64: Irix64  10
  15. os_canon:     NEXTSTEP: NextStep 11
  16. os_canon:       BSD_OS: bsdi    12
  17. os_canon:      machten: machten 13
  18. os_canon:  CYGWIN32_NT: cygwin32 14
  19. os_canon:  CYGWIN32_95: cygwin32 15
  20. os_canon:      UNIX_SV: MP_RAS: 16
  21. os_canon:         MiNT: FreeMiNT 17
  22. os_canon:       OS/390: OS/390  18
  23. os_canon:       VM/ESA: VM/ESA  19
复制代码
signature_type 字段标识了下一个 数据块 signature 的类型,在 RPM version 3.0 中,这个变量的值是 5.

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43ChinaUnix元老
日期:2015-01-30 15:14:07
发表于 2012-11-15 13:43 |显示全部楼层
感谢这么精彩的原创分享啊!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP