摘要: rpm 包是预先在 Linux 主机上编译好并打包的文件, 安装起来非常快捷. 不需要再进行繁琐的编译等操作, 拿来就能用, 区别于 yum 包管理, rpm 可以在不需要网络环境的情况下使用. 学习完大神的文章还是有一些细节不太清楚, 下面我就再对编译 RPM 包的过程和详细知识点再梳理扩展一下留作备忘.
简介
RedHat 包管理器 rpm(RedHat package manager), 因为非常的方便, 所以这个方式被广泛的使用现在 rpm 的英文翻译是一种递归写法(RPM package manager).RPM 是以一种数据库记录的方式来将所需要的套件安装在 Linux 主机的一套管理程序. 也就是说 Linux 系统中存在一个关于 rpm 的数据库, 它记录了安装的包与包之间的依赖相关性. 我们可以在有网的环境下载 rpm 包, 也可以定制化的将自己的软件打成 rpm 包.
准备 rpm 打包环境
我这里用的操作系统是 CentOS6.7,RedHat 系的其它发行版应该也类似.
安装 rpm-build
sudo yum install -y gcc make rpm-build RedHat-rpm-config VIM lrzsz
在无网络的机器上装备环境
需要在无网络的情况下解决一些依赖包的环境可以使用以下命令提前在一台有网络的机器上下载好 RPM 包再到无网络的机器上安装就可以了
yum install --downloadonly --downloaddir=<目录> <packages>
创建必须的文件夹和文件
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}echo '%\_topdir %(echo $HOME)/rpmbuild'> ~/.rpmmacros
文件名 | 类型 | 说明 |
---|---|---|
SPECS | 目录 | 包含 rpm 的 xxx.spec 文件 (打包的描述文件) |
SOURCES | 目录 | 包含源码包 (如. tar 包) 和所有 patch 补丁、service 启动文件等 |
BUILD | 目录 | 源码包被解压至此, 并在该目录的子目录完成编译 |
BUILDROOT | 目录 | 存放编译后的文件的临时目录 (保存 %install 阶段安装的文件) |
RPMS | 目录 | 经过编译成功后, 打包文件放在这个目录, 包含 i386、i686、noarch 等次级目录 |
SRPMS | 目录 | 包含. src.rpm 的 SPRM 包(通常用于审核和升级软件包) |
制作 spec 文件
找 spec 模板文件
一般找一个类似的 rpm 源码包, 将其安装, 然后参照它写自己软件包的 spec 文件.
- mkdir ~/rpms
- wget -O ~/rpms/python-2.6.6-64.el6.src.rpm http://vault.centos.org/6.7/os/Source/SPackages/python-2.6.6-64.el6.src.rpm
- rpm -ivh ~/rpms/python-2.6.6-64.el6.src.rpm
- VIM ~/rpmbuild/SPECS/python.spec # 参照这个文件来写自己软件包的 spec 文件
rpmbuild 内置变量
rpmbuild --showrc 可查看内置的变量
常用的几个变量:
- $RPM_BUILD_DIR /$HOME/rpmbuild/BUILD
- $RPM_BUILD_ROOT /$HOME/rpmbuild/BUILDROOT
- %{
- _sysconfigdir
- } /etc
- %{
- _sbindir
- } /usr/sbin
- %{
- _bindir
- } /usr/bin
- %{
- _prefix
- } /usr
- %{
- _localstatedir
- } /var
更多的可以查看 --showrc
rpmbuild spec 规范说明
Summary: 软件包的内容概要描述
Name: 软件包的名称(spec 文件名与其一致)
Version: 软件的实际版本号, 具体和源码包一致
Release: 软件包的发布实际版本号
Url: 软件的主页
License: 软件授权方式(GPL 等)
Group: 软件分组, 如(Application/System)
Source: 软件的来源
Patch: 补丁 patch file 依赖的软件, 安装的时候需要检查的
BuildRoot: 安装或者编译时使用的 "虚拟目录", 一般默认
BuildRequires: 编译过程中需要的软件
Requires: 依赖的软件, 安装的时候需要检查的
Packager: 软件的打包者
Vendor: 软件发行商或者打包组织信息, 如(Apache Software Foundation)
%description: 软件包描述
%prep: 编译前预处理. 如: 1. 打补丁; 2. 解压源码等
%setup: 解压源码(一般是位于 %prep 下的 macro, 自动解压源码)
%build: 编译
%install: 安装, 即把一些可执行文件和配置复制到目标目录中.
%clean: 清理一些暂存文件
%files: 定义哪些文件或者目录会放入 rpm 中
%pre: rpm 安装前执行的动作
%post: rpm 安装后执行的动作
%preun: 卸载前执行脚本程序 (preun) 开始执行
%postun: 卸载后执行脚本程序 (postun) 开始执行
更多参考:
rpmbuild spec 示例
示例 1 openstack-aodh.spec
- %global pypi_name aodh
- %{
- !?upstream_version: %global upstream_version %{
- version
- }%{
- ?milestone
- }
- }
- Name: openstack-aodh
- Version: 2.0.0
- Release: %{
- es_versions
- }%{
- ?dist
- }
- Summary: OpenStack Telemetry Alarming
- License: ASL 2.0
- URL: https://github.com/openstack/aodh.git
- BuildArch: noarch
- Source0: http://tarballs.openstack.org/%{
- pypi_name
- }/%{
- pypi_name
- }-%{
- version
- }.tar.gz
- ...
- %description
- Aodh is the alarm engine of the Ceilometer project.
- %prep
- %setup -q -n %{
- pypi_name
- }-%{
- upstream_version
- }
- %build
- %{
- __python2
- } setup.py build
- %install
- %{
- __python2
- } setup.py install --skip-buid --root %{
- buildroot
- }
- %files -n python-aodh
- %{
- python2_sitelib
- }/aodh
- ...
- %files common
- %doc README.rst
- %dir %{
- _sysconfdir
- }/aodh
- %attr(-, root, aodh) %{
- _datadir
- }/aodh/aodh-dist.conf
- %config(noreplace) %attr(-, root, aodh) %{
- _sysconfdir
- }/aodh/aodh.conf
- ...
- %changelog
示例 2 mariadb.spec
- %define debug_package %{nil}
- %define install_dir /usr/local/mariadb
- Name: mariadb
- Version: 10.1.20
- Release: 1%{?dist}
- Summary: Mariadb client programs and shared libraries and server programs
- Group: Applications/Databases
- License: GPLv2 with exceptions
- URL: https://mariadb.org/
- Source0: mariadb-10.1.20.tar.gz
- BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
- BuildRequires: readline-devel, openssl-devel
- BuildRequires: gcc-c++, ncurses-devel, zlib-devel
- BuildRequires: libtool, automake, autoconf, gawk
- Requires: grep, automake, autoconf, bash
- Autoreq: 0
- %description
- MariaDB Server is one of the most popular database servers in the world. It's made by the original developers of MySQL and guaranteed to stay open source. Notable users include Wikipedia, WordPress.com and Google.
- %prep
- %setup -q
- %build
- cmake . -DMYSQL_UNIX_ADDR=/tmp/mariadb.sock \
- -DEXTRA_CHARSETS=all \
- -DMYSQL_USER=MySQL \
- -DCMAKE_INSTALL_PREFIX=%{install_dir} \
- -DMYSQL_DATADIR=/data/mariadb \
- -DWITH_XTRADB_STORAGE_ENGINE=1 \
- -DWITH_FEDERATEDX_STORAGE_ENGINE=1 \
- -DWITH_ARCHIVE_STORAGE_ENGINE=1 \
- -DWITH_MYISAM_STORAGE_ENGINE=1 \
- -DWITH_INNOBASE_STORAGE_ENGINE=1 \
- -DWITH_ARCHIVE_STPRAGE_ENGINE=1 \
- -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
- -DWITH_SSL=system \
- -DVITH_ZLIB=system \
- -DWITH_LOBWRAP=0 \
- -DDEFAULT_CHARSET=utf8 \
- -DDEFAULT_COLLATION=utf8_general_ci \
- -DENABLED_LOCAL_INFILE=ON \
- -DWITH_PARTITION_STORAGE_ENGINE=1 \
- -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
- -DWITH_READLINE=ON \
- -DWITH_WSREP=ON \
- -DWITH_INNODB_DISALLOW_WRITES=ON \
- -DWITH_TOKUDB=1 \
- -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ \
- -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc \
- -DCMAKE_BUILD_TYPE:STRING=RELEASE
- make %{?_smp_mflags}
- %install
- rm -rf %{buildroot}
- make install DESTDIR=%{buildroot}
- %pre
- groupadd -r MySQL 2> /dev/null
- useradd -g MySQL -r -M -s /sbin/nologin MySQL 2> /dev/null
- mkdir -p /data/mariadb/data 2> /dev/null
- mkdir -p /data/mariadb/binlog 2> /dev/null
- mkdir -p /data/mariadb/undolog 2> /dev/null
- mkdir -p /var/run/mariadb/ 2> /dev/null
- mkdir -p /var/log/mariadb/ 2> /dev/null
- chown -R MySQL.MySQL /var/run/mariadb/ 2> /dev/null
- chown -R MySQL.MySQL /var/log/mariadb/ 2> /dev/null
- chown -R MySQL.MySQL /data/mariadb 2> /dev/null
- %clean
- rm -rf %{buildroot}
- %files
- %defattr(-, root, root, 0755)
- %{install_dir}/
- %doc
- %changelog
spec 更加详细内容见 这里
制作 rpm 包
上传必要的 source 文件
cp ${some_where}/Python-2.7.10.tgz ~/rpmbuild/SOURCES/
开始制作
- cd ~/rpmbuild
- rpmbuild -bb --target x86_64 SPECS/python27-tstack.spec> rpmbuild.log &
一切顺利的话, 最终会在~/rpmbuild/RPMS/x86_64 / 目录下找到编译好的 rpm 包.
技巧总结
不打 debug 的 rpm 包: 在 spec 文件中加入
%debug\_package %{nil}
即可
禁止自动分析源码添加不应该加入的依赖 在 spec 文件中加入 Autoreq: 0 即可
sepc 文件中一些宏的用法 在 spec 文件中经常出现一些宏, 比如 %setup,%patch, 这两个宏的选项较多, 使用时要特别注意, 参见这里
安装卸载 rpm 包前后的动作 可以通过 %pre, %post, %preun, %postun 指定 rpm 包在安装卸载前后的动作, 比如在安装前用脚本做一些准备, 在安装后用脚本做一些初始化动作, 在卸载前用脚本做一些准备, 在卸载后用脚本做一些清理动作
rpmbuild 命令的选项 rpmbuild 命令有不少选项, 参见这里 http://ftp.rpm.org/max-rpm/rpmbuild.8.html , 用得比较多的有:
-bp 只解压源码及应用补丁
-bc 只进行编译
-bi 只进行安装到 %{buildroot}
-bb 只生成二进制 rpm 包
-bs 只生成源码 rpm 包
-ba 生成二进制 rpm 包和源码 rpm 包
--target 指定生成 rpm 包的平台, 默认会生成 i686 和 x86_64 的 rpm 包, 但一般我只需要 x86_64 的 rpm 包
RPM 常用参数备忘
rpm -ivh ***.rpm: 安装软件(并且显示安装进度 --install--verbose--hash)
rpm -Uvh ***.rpm: 升级软件(--Update)
rpm -e: 卸载软件
rpm -q [软件名称]: 查询程序是否安装
rpm -qa: 查询已经安装的所有软件(Query All)
rpm -qi [软件名称]: 列出该软件的详细信息
rpm -qf [指定文件名]: 查找指定文件属于哪个 RPM 软件包(Query Files)
rpm -qc [软件名称]: 列出该软件的所有文件
rpm -qpi [软件名称]: 列出 RPM 软件包的描述信息(Query Packages install package(s))
rpm -qpl [软件名称]: 列出该软件的所有文件(Query Packages list)
rpm -qRp [软件名称]: 列出该软件的依赖(Query Rely Packages)
rpm -Va [软件名称]: 校验所有的 RPM 软件包, 查找丢失的文件(View List)
其他
如何从 python 源码包构建 rpm
在 python 源码目录执行
python setup.py bdist_rpm # 即可在当前 dist 目录下生成 rpm 包
定制 spec:
- python setup.py bdist_rpm --spec-only # 只生成 dist/<module>.spec
- # 重新编辑 dist/<module>.spec
- python setup.py bdist_rpm --spec-file=dist/<module>.spec
无污染地打 rpm 包
方法一, 使用 mock 来进程打包, 详细的过程可以见
CentOS 下无污染地打 rpm 包
mock 编包一般是做发行版本给别人使用, 当然你做的软件要能在别人机器上跑, 那么在开发过程中, 我们必须模拟一个纯净的用户环境(即是所谓的 chroot),mock 在编包前先构建一个这样的用户环境, 然后里面再使用 rpmbuild 的机制编包.
总结来说, rpmbuild 编出来的包是特例, 而 mock 编出来包在具有共性. mock 相当于给 rpmbuild 增加了一个外壳, 包装了一下.
方法二, 虚拟机操作
建议使用虚拟机操作, 不要在自己的电脑上进行这些操作, 不然到时候弄一大堆的包在自己电脑上很头疼的, 如果没有虚拟机可以使用 Vagrant 在本地虚拟化出一个 os 进行操作 具体用法使用 Vagrant 打造跨平台开发环境 https://segmentfault.com/a/1190000000264347
- mkdir some-dir
- cd some-dir
- Vagrant init CentOS/6
- Vagrant up
- Vagrant SSH
这两种方法各有各的好处, mock 感觉有点像 dock, 只要编译完成后直接删除该 mock 环境就行, 更加的纯洁迅速; 而 Vagrant 如果没有理解错他就是在本地安装了一个虚拟机, 比起 mock 更重一些, 但是可以比较轻松的应对更多的场景, 比如说在本地开发的时候代码可以在不同的时候上调试, 以后有时间一定要学习下这两种方式.
总结
rpmbuild 打包一般步骤
根据 rpmbuild 标准, 创建打包的目录结构
将源码和辅助文件放到指定目录
编写 spec 文件, 放到指定目录
根据需要构建 rpm, 或者 rpm 和 srpm 等.
无网络时提前在有网络的机器上下载好依赖包就好啦
引用
How to create an RPM package/zh-hk
CentOS6 下 rpm 打包实战
CentOS 6 制作 rpm 包
Linux 之 rpm 本地打包
SRPM 包编译成 RPM 包之 rpmbuild 和 mock
来源: https://www.qcloud.com/developer/article/1416295