Skip to Content

CentOS 如何打 RPM 包

Posted on 3 mins read

打包前的准备

安装相关打包工具

  • sudo yum install rpmdevtools rpmlint
  • rpmbuild --version
❯ rpmbuild --version                                                                                                                                                                                                                                                        z@z
RPM 版本 4.11.3

新建用户

RPM 在打包的过程中会将文件临时安装到系统中,为了保证构建程序不破坏系统环境,要使用普通用户打包:

sudo useradd rpmuser
sudo passwd rpmuser
su - rpmuser

初始化打包环境

rpmdev-setuptree是rpmdevtools中带的初始化环境脚本,执行后会在用户主目录下创建rpmbuild目录和.rpmmacros文件,同时生成所需的子目录和默认的控制参数,执行:

rpmdev-setuptree

生成的目录结构:

`-- rpmbuild
    |-- BUILD
    |-- RPMS
    |-- SOURCES
    |-- SPECS
    `-- SRPMS

默认的全局控制宏文件.rpmmacros内容:

%_topdir %(echo $HOME)/rpmbuild

%_smp_mflags %( \
    [ -z "$RPM_BUILD_NCPUS" ] \\\
        && RPM_BUILD_NCPUS="`/usr/bin/nproc 2>/dev/null || \\\
                             /usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
    if [ "$RPM_BUILD_NCPUS" -gt 16 ]; then \\\
        echo "-j16"; \\\
    elif [ "$RPM_BUILD_NCPUS" -gt 3 ]; then \\\
        echo "-j$RPM_BUILD_NCPUS"; \\\
    else \\\
        echo "-j3"; \\\
    fi )

%__arch_install_post \
    [ "%{buildarch}" = "noarch" ] || QA_CHECK_RPATHS=1 ; \
    case "${QA_CHECK_RPATHS:-}" in [1yY]*) /usr/lib/rpm/check-rpaths ;; esac \
    /usr/lib/rpm/check-buildroot

安装编译软件

制作rpm包要先编译在打二进制包,所以要装 gcc、make 等工具,如果是给 Golang 的项目打 RPM 包,还需要有 go 环境

yum install gcc gcc-c++ make

开始打包

准备源码

将源码包和补丁等放入rpmbuild/SOURCE目录

编写 SPEC 文件

SPEC文件控制整个rpm的打包过程,包含了打包的全部信息和控制参数,可以使用 rpmdev-newspec 命令来创建一个初始的SPEC文件,SPEC文件需放入rpmbuild/SPECS目录

rpmdev-newspec  package-name.spec

SPEC 脚本文件名需以包名一致,/etc/rpmdevtools/spectemplate-* 下有许多常用软件 RPM 打包的 SPEC 文件模板。

SPEC 脚本主要定义了打包过程中的几个阶段的配置:

  1. 信息定义阶段 :定义软件包的名字、版本等信息和打包过程中用到的变量等
  2. 制作准备阶段 :解压源码包、补丁包并打补丁
  3. 编译阶段 :设置编译参数并编译源码
  4. 安装阶段 :定义安装过程所执行的命令,包括安装前、安装后、卸载前、卸载后执行的操作
  5. 清理阶段 :清理打包过程中用到的目录文件等
  6. 文件设置阶段 :要打包的文件和目录,并设置文件权限等

下面是打包 motan-go 所使用 SPEC 文件(motan-go.spec):

# 自定义宏
%define bindir /data1/weibo/motan-go

# 1.信息定义阶段

### 软件名字,要与spec的文件名一致 openresty
Name:           motan-go
### 软件主版本号
Version:        1.0
### 发行编号,每打包一次值递增,主版本号发布新版后需重置该值
Release:        4%{?dist}
### 一行简短的软件简介,结尾不要加标点
Summary:        Motan is Weibo RPC
Group:          Weibo Motan G.
### 软件许可
License:        Apache License 2.0
### 软件项目主页
URL:           http://git.intra.weibo.com/openapi_rd/motan-go/
### 放置在SOUIRCES目录的软件源码包名,可以指定多个:source1、source2等
Source0:        %{name}.%{version}.tar.gz  
### 补丁名,也可以写多个 patch1、patch2等 
#patch0:            0.patch 
### 在 install 阶段的测试安装目录,方便写files
buildroot:      %_topdir/BUILDROOT
BuildRequires:  go
### 安装软件包时所需的依赖包列表,可以指定版本如 bash >= 1.1.1
Requires:       readline-devel,pcre-devel,openssl-devel
### 程序的详细多行描述,每行必须小于等于 80 个字符,空行表示开始新段
%description
Motan java.go.php

# 2.准备阶段
%prep
## 静默模式解压并进入解压后的目录,也常用:%autosetup -n %{name}
%setup -q -n motan-go   
### 需要打补丁,在这里写打补丁的命令                         
#%patch0 -p1

# 3. 编译阶段
%build

### 编译参数
#./configure
#使用多核处理器并行编译 
#make %{?_smp_mflags}  
cd main/
go build magent.go

# 4.安装阶段
%install
### 删除之前的残留文件
rm -rf %{buildroot}
mkdir -p %{buildroot}/%{bindir}/bin
install -m755 main/magent %{buildroot}/%{bindir}/bin/
install -d -m755 %{buildroot}/%{bindir}/bin/
cp -pvr motan.yaml %{buildroot}/%{bindir}/

## rpm安装前制行的脚本
%pre
### $1==1 代表的是第一次安装,2代表是升级,0代表是卸载
#if [ $1 == 1 ];then     
#     /usr/sbin/useradd -r %{nginx_user} 2> /dev/null 
#fi

## rpm安装后制行的脚本
%post

###卸载前执行的脚本
%preun
###卸载后执行的脚本
%postun

# 5.清理阶段
%clean
### 删除buildroot目录
rm -rf %{buildroot}

#  6.文件设置阶段
%files
### 设定默认权限,如果下面没有指定权限,则继承默认
%defattr (-,root,root,0755)
###要打包的文件和目录,在执行完rpmbuild -bi后,参考%{rootbuild}下生成的文件和目录
%{bindir}/bin/magent
/data1/weibo/motan-go

###  变更日志 格式固定,生成请用命令: rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
#%changelog
#* Thu Dec 31 2015 will <will@52os.net> - 1.9.7.1-4
#- openresty init

%define __debug_install_post %{_rpmconfigdir}/find-debuginfo.sh %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}" %{nil}

编写完 SEPC 文件后,可以通过 rpmlint 检查是否有配置错误

rpmlint motan-go.spec

如果有错误或者警告,使用 “-i” 选项可以查看更详细的信息

开始打 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 motan-go.spec
rpmbuild -bc motan-go.spec
rpmbuild -bi motan-go.spec
rpmbuild -bl motan-go.spec
rpmbuild -ba motan-go.spec

分阶段测试,方便排错,如果哪个阶段有错误,可以使用–short-circuit跳过之前成功的阶段,节省时间

rpmbuild -bi --short-circuit  ngx_openresty.spec

打包遇到的问题

extracting debug info from /home/rpmuser/rpmbuild/BUILDROOT/motan-go-1.0-4.el7.centos.x86_64/data1/weibo/motan-go/bin/magent
*** ERROR: No build ID note found in /home/rpmuser/rpmbuild/BUILDROOT/motan-go-1.0-4.el7.centos.x86_64/data1/weibo/motan-go/bin/magent
错误:/var/tmp/rpm-tmp.ozJYbO (%install) 退出状态不好

解法: 在 SPEC 文件中添加一行

%define __debug_install_post %{_rpmconfigdir}/find-debuginfo.sh %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}" %{nil}

参考资料:

centos下制作RPM包并签名 Centos 6 制作 rpm 包

comments powered by Disqus