centos下制作RPM包并签名
一、准备制作环境
我系统是centos 6.6 64位,rpmdevtools 版本为7.5,rpm-build版本为4.8,本文以制作openresty-1.9.7.1的rpm包为例。
1.1 安装打包工具
制作rpm包主要用到rpmbuild工具,rpmdevtools套件包含了rpmbuild等软件,同时又提供了很多有用的脚本,安装:
yum install rpmdevtools
spec配置检查工具:
yum install rpmlint
查看下rpmbuild的版本:
rpmbuild --version
RPM version 4.8.0
1.2 新建用户
rpm包在打包过程中,会将文件临时安装到系统中,为了保证构建程序不破坏系统,要使用普通用户打包:
useradd rpmuser
su - rpmuser
1.3 初始化打包环境
rpmdev-setuptree是rpmdevtools中带的初始化环境脚本,执行后会在用户主目录下创建rpmbuild目录和.rpmmacros文件,同时生成所需的子目录和默认的控制参数,执行:
rpmdev-setuptree
生成的目录结构:
rpmbuild/
├── BUILD #打包过程中的工作目录
├── RPMS #RPM包存放目录
├── SOURCES #源码和补丁目录
├── SPECS #SPEC文件目录
└── SRPMS #src rpm包存放目录
默认的全局控制宏文件.rpmmacros内容:
cat ~/.rpmmacros
%_topdir %(echo $HOME)/rpmbuild
%_smp_mflags -j3
%__arch_install_post /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot
1.4 安装编译软件
制作rpm包要先编译在打二进制包,所以要装gcc、make等工具:
yum install gcc gcc-c++ make
准备环境就结束了
二、制作RPM包
以打包openresty为例
2.1 下载源码包
将源码包和补丁等放入rpmbuild/SOURCE目录:
cd rpmbuild/SOURCE
wget https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz
2.2 编写SPEC文件
SPEC文件控制整个rpm的打包过程,包含了打包的全部信息和控制参数,可以使用 rpmdev-newspec 命令来创建一个初始的SPEC文件,SPEC文件需放入rpmbuild/SPECS目录:
rpmdev-newspec ngx_openresty.spec
这个脚本也自带了一些软件的模版,在/etc/rpmdevtools/spectemplate-*。spec文件主要定义了打包过程中的几个阶段的配置:
- 信息定义阶段 :定义软件包的名字、版本等信息和打包过程中用到的变量等
- 制作准备阶段 :解压源码包、补丁包并打补丁
- 编译阶段 :设置编译参数并编译源码
- 安装阶段 :定义安装过程所执行的命令,包括安装前、安装后、卸载前、卸载后执行的操作
- 清理阶段 :清理打包过程中用到的目录文件等
- 文件设置阶段 :要打包的文件和目录,并设置文件权限等
主要就是以上几个阶段,其中用到的宏比较多,看起来容易晕,遇到不明白的可以查最下面的参考文章。
附上ngx_openresty.spec文件:
## 1. 信息定义阶段
### 自定义宏,不是必须
#自定义一个宏名字为nginx_user值为nginx,%{nginx_user}引用
%define nginx_user nginx
### 软件名字,要与spec的文件名一致 openresty
Name: ngx_openresty
### 软件主版本号,参考下载的源码包 tengine-2.1.1.tar.gz
Version: 1.9.7.1
### 发行编号,每打包一次值递增,主版本号发布新版后需重置该值
Release: 4%{?dist}
### 一行简短的软件简介,结尾不要加标点
Summary: OpenResty is a full-fledged web platform
### 安装后所属的组, 通过/usr/share/doc/rpm-4.8.0/GROUPS选择,部分发行版已经废除此标签
Group: System Environment/Daemons
### 软件许可
License: GPLv2
### 软件项目主页
URL: https://openresty.org/
### 放置在SOUIRCES目录的软件源码包名,可以指定多个:source1、source2等
Source0: %{name}-%{version}.tar.gz
### 补丁名,也可以写多个 patch1、patch2等
#patch0: 0.patch
### 在 install 阶段的测试安装目录,方便写files
#buildroot: %_topdir/BUILDROOT
### 编译过程所需的软件
BuildRequires: gcc,make
### 安装软件包时所需的依赖包列表,可以指定版本如 bash >= 1.1.1
Requires: readline-devel,pcre-devel,openssl-devel
### 程序的详细多行描述,每行必须小于等于 80 个字符,空行表示开始新段
%description
OpenResty is a full-fledged web platform by integrating the standard Nginx core,
LuaJIT, many carefully written Lua libraries, lots of high quality
3rd-party Nginx modules, and most of their external dependencies.
It is designed to help developers easily build scalable
web applications, web services, and dynamic web gateways.
this rpm created by nixops.me
### 2.准备阶段
%prep
### 静默模式解压并进入解压后的目录,也常用:%autosetup -n %{name}
#%autosetup -n %{name}-%{version}.tar.gz
%setup -q
### 需要打补丁,在这里写打补丁的命令
#%patch0 -p1
### 3. 编译阶段
%build
### 编译参数
./configure \
--with-luajit \
--without-http_redis2_module \
--without-http_xss_module \
--without-http_memc_module \
--user=nginx \
--group=nginx \
#使用多核处理器并行编译
make %{?_smp_mflags}
### 4.安装阶段
%install
### 删除之前的残留文件
rm -rf %{buildroot}
### 指定安装目录为虚拟目录
#gmake install DESTDIR=%{buildroot}
gmake install DESTDIR=$RPM_BUILD_ROOT
#如果makefile不支持make install DESTDIR=$RPM_BUILD_ROOT,可以手写安装流程,即先建好目标目录,在复制文件
### rpm安装前制行的脚本
%pre
### $1==1 代表的是第一次安装,2代表是升级,0代表是卸载
if [ $1 == 1 ];then
/usr/sbin/useradd -r %{nginx_user} 2> /dev/null
fi
### 安装后执行的脚本
%post
###卸载前执行的脚本
%preun
if [ $1 == 0 ];then
/usr/sbin/userdel -r %{nginx_user} 2> /dev/null
fi
### 卸载后执行的脚本
%postun
### 5.清理阶段
%clean
### 删除buildroot目录
rm -rf %{buildroot}
### 6.文件设置阶段
%files
### 设定默认权限,如果下面没有指定权限,则继承默认
%defattr (-,root,root,0755)
###要打包的文件和目录,在执行完rpmbuild -bi后,参考%{rootbuild}下生成的文件和目录
/usr/
### 变更日志 格式固定,生成请用命令: rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
%changelog
* Thu Dec 31 2015 will <will@nixops.me> - 1.9.7.1-4
- openresty init
编辑好ngx_openresty.spec文件后检查一下配置是否有错误:
rpmlint ngx_openresty.spec
如果有错误或者警告,使用 "-i" 选项可以查看更详细的信息
2.3 开始打包rpm
rpmbuild命令会根据spec文件来生成rpm包,主要用到以下几个参数:
rpmbuild --help
-bp 执行到%prep阶段结束
-bc 执行到%build阶段结束
-bi 执行到%install阶段结束
-bl 检测%files文件是否有丢失
-ba 创建src.rpm和二进制包
-bs 只创建src.rpm源码包
-bb 只创建二进制rpm包
常用的参数就这几个,其它的自己看man手册,开始打包:
rpmbuild -bp ngx_openresty.spec
rpmbuild -bc ngx_openresty.spec
rpmbuild -bi ngx_openresty.spec
rpmbuild -bl ngx_openresty.spec
rpmbuild -ba ngx_openresty.spec
分阶段测试,方便排错,如果哪个阶段有错误,可以使用--short-circuit跳过之前成功的阶段,节省时间:
rpmbuild -bi --short-circuit ngx_openresty.spec
我这个spec文件为了省事,没有手写%install过程,导致rpmbuild -bi会报一个RPATH错误,不影响打包,但是要跳过:
QA_RPATHS=$[ 0x0002|0x0010 ] rpmbuild -ba ngx_openresty.spec
到这里就会在RPMS目录和SRPMS目录生产对应的rpm包,用root进行安装测试:
rpm -ivh RPMS/x86_64/ngx_openresty-1.9.7.1-4.el6.x86_64.rpm
默认安装到/usr/local/openresty,测试程序是否正常运行,卸载:
rpm -e ngx_openresty-1.9.7.1-4.el6.x86_64
三、RPM包签名
对rpm包进行签名可以防止软件包被篡改,像epel、remi等公共软件源都会使用签名,签名要用到gnupg软件包,查询是否安装:
rpm -qf `which gpg`
3.1 生成密钥对
此过程要用root执行,使用普通用户会出现错误
gpg --gen-key
Please select what kind of key you want: 默认
What keysize do you want? (2048) 默认
Key is valid for? (0) 默认
is this correct? (y/N) y
Real name: willis 名字
Email address: willis@nixops.me 邮箱
Comment: GPG-RPM-KEY
hange (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
这步之后会要求输入密码,可以为空
生成密钥对时会使用/dev/random生成的真随机数(通过噪音产生),可能会因熵池不够而阻塞,需要安装rng-tools自动补充熵池:
yum install rng-tools
在 /etc/sysconfig/rngd中添加:
EXTRAOPTIONS="-r /dev/urandom"
启动:
service rngd start
查看熵池大小:
cat /proc/sys/kernel/random/entropy_avail
如果是几十,产生密钥对时就会卡住
将/root/.gnupg 移到 /home/rpmuser,并将权限改为rpmuser:
mv /root/.gnupg /home/rpmuser
chown rpmuser.rpmuser /home/rpmuser/ -R
切换到rpmuser查看公钥:
gpg --list-keys
3.2 rpm软件包签名
切换回rpmuser,在~/.rpmmacros中添加:
%_signature gpg
%_gpg_name willis
对rpm软件包签名:
rpm --addsign ngx_openresty-1.9.7.1-4.el6.x86_64.rpm
Enter pass phrase: gpg密码,这里没有设置
Pass phrase is good.
ngx_openresty-1.9.7.1-4.el6.x86_64.rpm:
在rpmbuild打包时签名:
rpmbuild --sign --bb ~/rpmbuild/SPECS/ngx_openresty.spec
3.3 验证签名
验证软件包签名要将公钥导入到rpm的数据库中,然后用rpm命令验证,导出公钥:
gpg --export -a willis >GPG-RPM-KEY-nixops
查看当前rpm数据库中已有的公钥:
rpm -q gpg-pubkey-*
gpg-pubkey-c105b9de-4e0fd3a3
gpg-pubkey-0608b895-4bd22942
使用root导入到rpm数据库中:
rpm --import GPG-RPM-KEY-nixops
在查询一下:
rpm -q gpg-pubkey-*
gpg-pubkey-c105b9de-4e0fd3a3
gpg-pubkey-0608b895-4bd22942
gpg-pubkey-a2bc02d9-56849054
最后一个就是导入的公钥,验证签名:
rpm -K rpmbuild/RPMS/x86_64/ngx_openresty-1.9.7.1-4.el6.x86_64.rpm
rpmbuild/RPMS/x86_64/ngx_openresty-1.9.7.1-4.el6.x86_64.rpm: rsa sha1 (md5) pgp md5 OK
验证成功
参考文章:
https://fedoraproject.org/wiki/How_to_create_an_RPM_package/zh-cn
http://laoguang.blog.51cto.com/6013350/1103628
http://www.worldhello.net/2011/04/12/2442.html