在生产环境下,未确保软件版本的可靠及软件的稳定性,我们一般不使用源码安装软件。一般会根据os的不同,选择apt-get或yum安装软件。
本文主要讲解如何使用rpmbuild工具制作rpm包。并以Openstack为例,讲述了Openstack打包的过程。
RPM基础知识
本节主要分析是什么以及为什么的问题。
以及常用的rpm和yum命令。
RPM包管理是什么?
RPM全称是RedHat Package Manager,是红帽系Linux默认使用的软件管理方法。主要包括centos、fedora、rhel等Linux分支。
其格式为Linux标准(LSB),是数据库驱动的包管理解决方案。
配合软件源,在centos系操作系统下,使用yum命令(最新版本应该是逐渐向dnf过渡)可以很容易的解决软件安装时的版本依赖问题。
为什么使用RPM包管理?
RPM包管理的优点如下:
- 易于分发,安装、卸载、升级
- 自动依赖跟踪,结合yum自动解决依赖问题
- 自带包验证,保证安装的正确性
- 保存软件包安装的一致性
- 易于保持对系统安装包的跟踪管理
基本RPM命令
我们可以直接使用rpm命令,对软件包进行一些操作。
- 安装
rpm –ivh <package_name>
--nodeps
忽略依赖问题,一般仅用于测试 卸载
rpm –e <package_name>
有其它包依赖此RPM包时,卸载会报错升级
升级时使用-ivh会提示文件冲突rpm –Uvh <package_name>
没有安装过,则安装rpm –Fvh <package_name>
没有安装过,则忽略查找
rpm –q[option] <package name>
-q 仅查询是否安装
-qi 列出软件包的详细信息
-ql 列出软件包的目录及文件
-qf 列出文件对应的安装包
-qa 列出所有已安装的软件包
-qp 列出未安装的RPM包的信息验证
对已安装的包进行文件校验:rpm –V <package_name>
rpm -Vp <rpm_file>
rpm -Va
导入key:rpm --import <RPM_KEY>
在包安装之前进行签名校验:rpm -K <rpm_>file
重建数据库
rpm –rebuilddb
解决系统RPM数据库的异常
基本YUM命令
yum其实是透明的调用rpm,相当于在rpm基础上封装的更易使用的“前端”。
它主要设计来解决软件包之间的依赖性,并可从多个资源库(我们称之为“源”,典型的由/etc/yum.repos.d/
目录下的每个.repo文件定义)。
- 源制作
createrepo <dir>
一般的centos系的iso镜像中,都带有安装时使用的rpm包。可以将这部分文件mount到本地,创建本地源,以减少软件安装时的上网下载。 - 安装
yum install <package_name> -y
yum localinstall <rpm_file>
本地安装yum groupinstall <group_name>
组安装 - 升级
yum update [package_name]
- 卸载
yum remove/erase <package_name>
谨慎使用: 此命令会卸载掉所有依赖此包的RPM包 - 查找
yum search <name>
yum list|grep
本地缓存相关
yum makecache
只做本地缓存yum clean all
清除本地缓存repo文件格式
一个典型的repo文件格式如下:[repo-name]
name=repo-name
baseurl=http://yourserver.com/path/to/repo
enabled=1
gpgcheck=0
RPM Build相关知识
环境搭建
- 软件包安装
yum install rpm-build -y
- 创建目录
~/rpmbuild: 默认使用主目录下的rpmbuild目录
~/rpmbuild/SPECS: 存放spec文件
~/rpmbuild/SOURCES : 存放源代码等source文件
~/rpmbuild/RPMS : 存放RPM包
~/rpmbuild/BUILD和~/rpmbuild/BUILDROOT: 存放build中间文件
rpmbuild命令
rpmbuild –ba
编译二进制及源RPM包rpmbuild –bb
仅编译二进制RPM包rpmbuild –bs
仅编译源RPM包
编译后的二进制RPM包在~/rpmbuild/RPMS/<arch>
目录下,如~/rpmbuild/RPMS/noarch
。
源RPM包在~/rpmbuild/SRPMS/
下。
Build准备
- 源码包
按SPEC文件中指定名称,放在SOURCES文件夹下 - patch、init脚本
按SPEC文件中指定名称,放在SOURCES文件夹下 - SPEC文件
放在SPECS文件夹下
SPEC文件语法
spec文件内容主要:
- 指定编译、安装源码的过程
- 编译和生成RPM包指令的集合
- 指定RPM包的内容及信息
语法与shell类似,也可直接使用shell命令。
Spec文件分为不同的节
不同的节用于不同的阶段,分别用于完成不同功能。
主要分为以下几个阶段:
- Preamble
- Setup
- Build
- Install
- Clean
- Files
- Changelog
Preamble
此节主要用于初始化,定义RPM包的特性:
- Name/Version/Group/License
- Release信息:BUILD版本号
- Sources/Patches:编译时使用的源代码及patch
- Requirements:使用Requires、BuildRequires指定依赖包及版本。
- Summary/Description
- 其它自定义属性
Setup
通过解压源码包等方式,生成需要的源码树
对源码进行patch等操作
build之前的所有其它操作,如删除不需要的文件
例子:
%prep #定义prep节开始 |
Build
编译二进制文件
可以使用%configure指定build时需要加入的参数
举例:
%build |
Install
创建BUILDROOT目录
在BUILDROOT中创建需要的目录结构
将编译后的文件安装在BUILDROOT对应位置
清理不需要的文件
可以通过%pre/%post/%preun/%postun
分别指定安装前、安装后、卸载前、卸载后要执行的动作。
举例:
%install #执行python setup.py install进行安装,跳过编译阶段 |
Clean
清理资源,如移除BUILDROOT目录
举例:
%clean |
Files
指定所有RPM安装的文件
Install但未指定的文件,会报错
举例:
%files |
Changelog
用于跟踪spec文件的修改记录
应该在每次修改后增加相关记录
举例:
%changelog |
常用的宏
使用宏,而不是指定绝对路径,增加灵活性。因为不同系统中,使用不同系统路径,spec文件无需修改。
内置宏定义在 /usr/lib/rpm/macros文件中。同时支持自定义宏。
# Built-in macros |
RPM Build最佳实践建议
总结的一些经验教训:
- 对于源码需要的修改,使用patch,而不是RPM Hacks
- 避免脚本,减少pre/post的使用,逻辑尽量放在代码中
- 使用Changelog或版本控制,便于查找及维护
- 避免使用root用户制作RPM包
- 在Fedora/EPEL中查找现成RPM包、SPEC文件
Openstack RPM制作
打包前准备
编写需要的SPEC文件及init脚本。或使用已有的SRPM包,如通过RDO:https://repos.fedorapeople.org/repos/openstack/。
- 解压SRPM找到spec文件,放在SPECS目录下
- 找到其他source文件,放在SOURCES目录下
- Git clone代码,压缩为SPEC文件指定的名称,放在SOURCES目录下
- 按需修改各文件
rpmbuild –ba <spec_file>
- 安装RPM包进行测试
以Nova为例
- SPEC文件
openstack-nova.spec - SOURCES
nova-2014.1.3.tar.gz
.init及.upstart文件,conf及logrotate等文件 - 需要的patch
- rpmbuild
rpmbuild –ba openstack-nova.spec
- 按照RDO文档依次安装RPM包搭建环境进行测试
各组件对应spec文件
- nova - openstack-nova.spec
- Neutron - openstack-neutron.spec
- Keystone - openstack-keystone.spec
- Glance - openstack-glance.spec
- Cinder - openstack-cinder.spec
- Swift - openstack-swift.spec
- Horizon - python-django-horizon.spec