Skip to Content

CentOS 如何打 RPM 包

Table of Contents

打包前的准备

安装相关打包工具

  • 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}

rpm 执行安装包

二进制包(Binary)以及源代码包(Source)两种。二进制包可以直接安装在计算机中,而源代码包将会由 RPM自动编译、安装。源代码包经常以src.rpm作为后缀名。

常用命令组合:

-ivh:安装显示安装进度–install–verbose–hash

-Uvh:升级软件包–Update;

-qpl: 列出RPM软件包内的文件信息[Query Package list];

-qpi:列出RPM软件包的描述信息[Query Package install package(s)];

-qf:查找指定文件属于哪个RPM软件包[Query File];

-Va:校验所有的 RPM软件包,查找丢失的文件[View Lost];

-e:删除包

rpm -q samba //查询程序是否安装

rpm -ivh /media/cdrom/RedHat/RPMS/samba-3.0.10-1.4E.i386.rpm //按路径安装并显示进度

rpm -ivh –relocate /=/opt/gaim gaim-1.3.0-1.fc4.i386.rpm    //指定安装目录

rpm -ivh –test gaim-1.3.0-1.fc4.i386.rpm    //用来检查依赖关系;并不是真正的安装;

rpm -Uvh –oldpackage gaim-1.3.0-1.fc4.i386.rpm //新版本降级为旧版本

rpm -qa | grep httpd      #[搜索指定rpm包是否安装]–all搜索httpd

rpm -ql httpd         #[搜索rpm包]–list所有文件安装目录

rpm -qpi Linux-1.4-6.i368.rpm #[查看rpm包]–query–package–install package信息

rpm -qpf Linux-1.4-6.i368.rpm #[查看rpm包]–file

rpm -qpR file.rpm       #[查看包]依赖关系

rpm2cpio file.rpm |cpio -div    #[抽出文件]

rpm -ivh file.rpm  #[安装新的rpm]–install–verbose–hash

rpm -ivhhttp://mirrors.kernel.org/fedora/core/4/i386/os/Fedora/RPMS/gaim-1.3.0-1.fc4.i386.rpm

rpm -Uvh file.rpm    #[升级一个rpm]–upgrade

rpm -e file.rpm      #[删除一个rpm包]–erase

常用参数:

Install/Upgrade/Erase options:

-i, –install                     install package(s)

-v, –verbose                     provide more detailed output

-h, –hash                        print hash marks as package installs (good with -v)

-e, –erase                       erase (uninstall) package

-U, –upgrade=+      upgrade package(s)

--replacepkge                    无论软件包是否已被安装,都强行安装软件包

–test                            安装测试,并不实际安装

–nodeps                          忽略软件包的依赖关系强行安装

–force                           忽略软件包及文件的冲突

Query options (with -q or –query):

-a, –all                         query/verify all packages

-p, –package                     query/verify a package file

-l, –list                        list files in package

-d, –docfiles                    list all documentation files

-f, –file                        query/verify package(s) owning file

RPM源代码包装安装

.src.rpm结尾的文件,这些文件是由软件的源代码包装而成的,用户要安装这类RPM软件包,必须使用命令:

rpm –recompile vim-4.6-4.src.rpm   #这个命令会把源代码解包并编译、安装它,如果用户使用命令:

rpm –rebuild vim-4.6-4.src.rpm  #在安装完成后,还会把编译生成的可执行文件重新包装成i386.rpm 的RPM软件包。

[root@localhost src]# rpm -ivh awstats-6.8-1.noarch.rpm

error: Failed dependencies:

perl(LWP::UserAgent) is needed by awstats-6.8-1.noarch

[root@localhost src]#

使用rpm 属性相依套件的档案

[root@localhost src]# rpm -qpR awstats-6.8-1.noarch.rpm

/bin/sh

/usr/bin/perl

config(awstats) = 6.8-1

perl >= 0:5.005

perl(LWP::UserAgent)

perl(POSIX)

perl(Socket)

perl(Time::Local)

perl(strict)

perl(vars)

rpmlib(CompressedFileNames) <= 3.0.4-1

rpmlib(PayloadFilesHavePrefix) <= 4.0-1

参考资料:

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

微信公众号 / Vanilla-OpenResty