通过RpmBuild构建redis-5.0.9版本的RPM类型包

系列文章目录

rpmbuild基础知识


前言

承接rpmbuild基础知识章节和对应的背景要求,开始着手下载redis源码包、编写spec文件、构建出符合要求的redis安装包,具体方法如下所示。


提示:以下构建文件及方式已在centos 7 x86_64系统架构上测试运行,一切均正常

一、rpmbuild相关操作

1、安装rpmbuild命令

[root@python2 ~]# yum install -y rpm-build
[root@python2 ~]#  yum install rpmdevtools

2、安装spec文件检查工具

[root@python2 ~]# yum install rpmlint -y

如果返回错误/警告,使用 “-i” 选项查看更详细的信
[root@python2 ~]#  rpmlint -i program.spec

也可以使用 rpmlint 测试已构建的 RPM 包,检查 SPEC/RPM/SRPM 是否存在错误。你需要在发布软件包之前,解决这些警告。此页面 提供一些常见问题的解释。如果你位于 SPEC 目录中,请执行:

[root@python2 ~]# rpmlint NAME.spec ../RPMS/*/NAME*.rpm ../SRPMS/NAME*.rpm

3、查看rpmbuild版本

[root@python2 ~]# rpmbuild --version
RPM version 4.11.3

4、编译工具安装

# 编译工具
[root@python2 ~]#  yum install -y gcc make  gcc-c++ 

5、修改rpm制作包的默认路径

[root@python2 ~]#  echo "%_topdir /export/rpmbuild"  >> /root/.rpmmacros
%_topdir /export/rpmbuild  #/root/.rpmmacros文件是存储各种宏定义,比如_topdir宏的值来自定义打包路径

二、资源准备

1、创建rpmbuild工作目录

手动创建
[root@python2 ~]#   mkdir -p /export/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
rpmdevtools 命令创建
[root@python2 ~]#   cd /export/
[root@python2 ~]#   rpmdev-setuptree

[root@python2 ~]#  cd /export/rpmbuild && ls
	BUILD  RPMS  SOURCES  SPECS  SRPMS

2、目录作用解释

默认位置宏代码名称用途
/export/rpmbuild/SPECS%_specdir文件目录保存 RPM 包配置(.spec)文件
/export/rpmbuild/SOURCES%_sourcedir源代码目录保存源码包(如 .tar 包)和所有 patch 补丁
/export/rpmbuild/BUILD%_builddir构建目录源码包被解压至此,并在该目录的子目录完成编译
/export/rpmbuild/BUILDROOT%_buildrootdir最终安装目录保存 %install 阶段安装的文件
/export/rpmbuild/RPMS%_rpmdir标准 RPM 包目录生成/保存二进制 RPM 包
/export/rpmbuild/SRPMS%_srcrpmdir源代码 RPM 包目录生成/保存源码 RPM 包(SRPM)

3、下载redis源码包

将源码包下载至SOURCES目录,专门用于存放源文件
[root@python2 ~]#  cd /export/rpmbuild/SOURCES
[root@python2 ~]#  wget  https://download.redis.io/releases/redis-5.0.9.tar.gz

4、上传redis.conf文件

[root@python2 ~]#  cd /export/rpmbuild/SOURCES
[root@python2 ~]#  rz
此处替换为自己环境现有的redis.conf文件即可

5、上传创建redis实例脚本和创建分布式集群脚本

将这两个脚本封装到rpm包中去,安装之后可快速执行脚本产生redis实例,并构建出相应的分布式集群

[root@python2 ~]#  cd /export/rpmbuild/SOURCES
[root@python2 ~]#  rz
create_port_redisconf.sh
#!/bin/bash
# help
useage() {
	echo -e "useage: $0 [ port ] [[yes|no cluster] default no]
	eg:$0 7889 no|yes\n"
	exit 2
}

redis_cluster_conf() {
    # redis config file
    cat > ${redis_dir}/conf/${port}/redis_${port}.conf << EOF

include ${redis_dir}/conf/redis.conf

daemonize yes

cluster-enabled yes
cluster-config-file "nodes.conf"
cluster-node-timeout 15000

pidfile "${redis_dir}/logs/redis_${port}.pid"
logfile "${redis_dir}/logs/redis_${port}.log"

appendonly no

dir "${redis_dir}/conf/${port}"
port ${port}
# Generated by CONFIG REWRITE
timeout 600
tcp-keepalive 3600
save 900 1
save 300 10
save 60 10000
client-output-buffer-limit normal 0 0 0
repl-timeout 180
repl-backlog-size 50mb
client-output-buffer-limit slave 0 0 0

EOF
}

redis_standard_conf(){
    # redis config file
    cat > ${redis_dir}/conf/${port}/redis_${port}.conf << EOF

include ${redis_dir}/conf/redis.conf

daemonize yes

pidfile "${redis_dir}/logs/redis_${port}.pid"
logfile "${redis_dir}/logs/redis_${port}.log"

appendonly no

dir "${redis_dir}/conf/${port}"
port ${port}
# Generated by CONFIG REWRITE
timeout 600
tcp-keepalive 3600
save 900 1
save 300 10
save 60 10000
client-output-buffer-limit normal 0 0 0
repl-timeout 180
repl-backlog-size 50mb
client-output-buffer-limit slave 0 0 0

EOF

}

#
if [[ $# -eq 1 && $1 -gt 0 ]] || [[ $# -eq 2 ]];then
    port=$1
    is_cluster=$2

    redis_dir='/export/server/redis'
    # create port dir
    [ -d ${redis_dir}/conf/${port} ] || mkdir -p ${redis_dir}/conf/${port}
    

    [ -f ${redis_dir}/conf/${port}/redis_${port}.conf ] && echo "${redis_dir}/conf/${port}/redis_${port}.conf File is exits!" && exit 2
    # 
    if echo "${is_cluster[@]}" | grep -w "yes" &>/dev/null;then
        # create redis config file
        redis_cluster_conf
    else
        # create redis config file
        redis_standard_conf
    fi
    # create start service file
    cat > ${redis_dir}/service_${port}.sh << EOF
#!/bin/bash

# help
useage() {
	echo -e "useage: \$0 [ start | stop | restart ]
	eg:\$0 start\\n"
	exit 2
}


start() {
    ${redis_dir}/bin/redis-server ${redis_dir}/conf/${port}/redis_${port}.conf 
}
stop() {
    kill -9 \`cat ${redis_dir}/logs/redis_${port}.pid\`
}

if [[ \$# -eq 1 ]];then
    case \$1 in
        start)
            start
    	    ;;
        stop)
            stop
    	    ;;
        restart)
            stop
            start
    	    ;;
        *)
            useage
    	    ;;
    esac
else
    useage
fi

EOF
    
    # add x mode
    chmod +x ${redis_dir}/service_${port}.sh
    

else
    useage
fi
create_clusterRedis.sh
#!/bin/bash

redis_home='/export/server/redis'


# help
useage() {
	echo -e "useage: $0 [ host1:port host1:port ... ]
	eg:$0 127.0.0.1:7001 127.0.0.1:7002 ...\n"
	exit 2
}

create() {
    ${redis_home}/bin/redis-cli --cluster create --cluster-replicas 1  $*
}

if [[ $# -gt 1 ]];then
    echo $*
    
    create $*

else
    useage
fi

至此,准备工作已完成,下面开始编写spec文件并构建RPM包

三、构建过程

提醒: 详细的rpmbuild相关宏定义、变量定义、构建分成的阶段等文档,在此处不进行细说,自行查看文章顶端的rpmbuild基础知识链接即可

1、redis.spec文件

[root@python2 ~]# cd /export/rpmbuild/SPEC/
[root@python2 SPEC/]# vim redis.spec
#自定义宏,相当于Linux中"Key-Value"变量形式
#--->名称
%define Name redis
#--->版本
%define Version 5.0.9
#--->本rpm包中需更换的配置文件
%define CONFIGFILE redis.conf
#--->本rpm包默认安装的路径
%define InstallPath /export/server/redis
#-->rpm包封装进去的脚本
%define create_port  create_port_conf.sh
%define create_cluster create_cluster.sh

%define _build_id_links none
# 软件包的名称 
Name: %{Name}
# 软件包的版本 
Version: %{Version}
# 软件包发布序列号,1表示第几次打包 %{?dist} 会再包名中添加操作系统系统
Release: 1
# 软件包的概要信息,不要超过50个 
Summary: The redis for centos 7 x86_64.

# 软件授权方式 
License: BSD

# 软件分类
Group:System Middleware

# 源代码软件包的官方地址或源码包的下载地址 
URL: https://download.redis.io/releases/redis-5.0.9.tar.gz



# 源代码软件包的名字 
Source0: %{Name}-%{Version}.tar.gz
Source1: %{CONFIGFILE}
Source2: %{create_port}
Source3: %{create_cluster}

# install使用的虚拟目录,安装后就在该目录下打包 
BuildRoot: %_topdir/BUILDROOT


#制作过程中用到的软件包
BuildRequires: gcc,automake,autoconf,libtool,make
Requires: bash,jemalloc

#软件包详细描述信息 
%description
This is %{Name}


%pre
if getent passwd %{Name} > /dev/null; then
    echo "user %{Name} already exist,The installation operation will continue!!!"
else
    useradd %{Name} -s /sbin/nologin
fi


# 安装前的准备工作,一般用于解压源码包
%prep
#解压并cd到相关目录  tar xf SOURCES/redis-5.0.9.tar.gz -C BUILD && cd BUILD
%setup -q

# 源码编译 make
%build
make %{?_smp_mflags}


# 源码安装
#目前还是在/export/rpmbuild/BUILD/目录中,执行以下操作
#rm -rf /export/rpmbuild/BUILDROOT
#mkdir -p /export/rpmbuild/BUILDROOT/export/server/redis/{bin,conf,data,logs,script}
%install
%{_rm} -rf %{buildroot} # 清理之前的安装
# 使用 make install 来自动安装到指定目录,替代手动复制文件的步骤
make install PREFIX=%{buildroot}%{InstallPath}

# 创建目录结构,如果make install没有创建(通常不需要,除非有特殊需求)
mkdir -p %{buildroot}%{InstallPath}/{conf,data,logs,script}

# 如果需要,创建必要的符号链接(检查是否已经由 make install 创建)
# ln -s %{buildroot}%{InstallPath}/bin/redis-server %{buildroot}%{InstallPath}/bin/redis-sentinel

# 复制自定义的或额外的配置文件和脚本
cp -rp %{SOURCE1} %{buildroot}%{InstallPath}/conf/
cp -rp %{SOURCE2} %{buildroot}%{InstallPath}/script/
cp -rp %{SOURCE3} %{buildroot}%{InstallPath}/script/
chmod +x %{buildroot}%{InstallPath}/script/*

# 设置文件和目录的所有权
chown -R redis.redis %{buildroot}%{InstallPath}


#卸载前需要做的任务 如:停止任务
%preun
if [ $1 -eq 0 ]; then
    echo "Automatically stopping all Redis services..."
    for script in %{InstallPath}/service_*.sh; do
        if [[ $script =~ service_([0-9]+)\.sh ]]; then
            sh $script stop
        fi
    done
    # RPM 卸载操作,备份或移动目录
    mkdir -p /export/backup/
    if [ -d %{InstallPath} ]; then
        cp -rp %{InstallPath}  /export/backup/
    fi
    echo "Redis data has been backed up to /export/backup/."
    
    userdel -r redis
    echo "Redis user has been deleted"
fi

#设置文件属性,包含编译文件需要生成的目录、文件以及分配所对应的权限
%files
%defattr(-,redis,redis,-)
%dir %{InstallPath}
%dir %{InstallPath}/bin
%dir %{InstallPath}/conf
%dir %{InstallPath}/data
%dir %{InstallPath}/logs
%dir %{InstallPath}/script
%{InstallPath}/bin/*
%{InstallPath}/conf/*
%{InstallPath}/script/*


#变更日志  第一行的变更时间格式 由date '+* %a %b %d %Y %T %z' 在命令获取然后粘贴即可
%changelog
* Fri Jul 05 2024 14:57:39 +0800
- Initial redis 5.0.9 RPM release

2、修改用户自定义宏相关文件rpmmacros

因为上述的redis.spec文件中引用了不少的宏变量,因此需要在此处定义

[root@python2 ~]# cat /root/.rpmmacros 
%_topdir /export/rpmbuild
%_rm    /usr/bin/rm
%_signature gpg
%_gpg_path /root/.gnupg/
%_gpg_name rpmbuild
%_gpgbin /usr/bin/gpg

3、创建RPM包签名

该流程和方法详情见文章顶部<rpmbuild基础知识>链接,查看RPM包签名流程部分即可

4、构建带签名的RPM包

在这里插入图片描述

#进入到SPEC文件目录下
[root@python2 rpmbuild]# cd SPECS/
[root@python2 SPECS]# ll
total 8
-rw-r--r-- 1 root root 4423 Jul  5 15:03 redis.spec
#执行构建命令
[root@python2 SPECS]# useradd redis -s /sbin/nologin  #先创建出redis用户,否则构建会报错
Creating mailbox file: File exists

[root@python2 SPECS]# rpmbuild --sign --bb redis.spec  #--sign 指的是构建RPM时指定RPM包签名

#构建过程
[root@python2 SPECS]# rpmbuild --sign --bb redis.spec 
+ umask 022
+ cd /export/rpmbuild/BUILD
+ cd /export/rpmbuild/BUILD
+ rm -rf redis-5.0.9
+ /usr/bin/gzip -dc /export/rpmbuild/SOURCES/redis-5.0.9.tar.gz
+ /usr/bin/tar -xf -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd redis-5.0.9
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
+ umask 022
+ cd /export/rpmbuild/BUILD
+ cd redis-5.0.9
+ make
    CC Makefile.dep
    ......  #全部过程就不在此展示了
9100 blocks
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
+ umask 022
+ cd /export/rpmbuild/BUILD
+ cd redis-5.0.9
+ /usr/bin/rm -rf /export/rpmbuild/BUILDROOT/redis-5.0.9-1.x86_64
+ exit 0
Enter pass phrase:   #这块是签名所要输入的密码地方,然后rpm包才真正的签名成功
Pass phrase is good.
/export/rpmbuild/RPMS/x86_64/redis-5.0.9-1.x86_64.rpm:
/export/rpmbuild/RPMS/x86_64/redis-debuginfo-5.0.9-1.x86_64.rpm:

5、查看结果

[root@python2 SPECS]# cd ../RPMS/x86_64/
[root@python2 x86_64]# ll
total 7300
-rw-r--r-- 1 root root 1364252 Jul  5 21:48 redis-5.0.9-1.x86_64.rpm  #这个才是构建出来的RPM包
-rw-r--r-- 1 root root 6107072 Jul  5 21:48 redis-debuginfo-5.0.9-1.x86_64.rpm

至此,通过SPEC文件构建rpm包已完成,具体的rpmbuild指令及spec文件中定义的宏,都可以去查看文章顶部的<rpmbuild基础知识>学习了解到

四、结果演示

1、安装构建完成的RPM包

[root@python2 x86_64]# ll
total 7300
-rw-r--r-- 1 root root 1364252 Jul  5 21:48 redis-5.0.9-1.x86_64.rpm
-rw-r--r-- 1 root root 6107072 Jul  5 21:48 redis-debuginfo-5.0.9-1.x86_64.rpm
[root@python2 x86_64]# rpm -ivh redis-5.0.9-1.x86_64.rpm 
Preparing...                          ################################# [100%]
user redis already exist,The installation operation will continue!!!
Updating / installing...
   1:redis-5.0.9-1                    ################################# [100%]

2、创建redis实例

#查看安装后的目录结构
[root@python2 redis]# tree
.
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof
│   ├── redis-check-rdb
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── conf
│   └── redis.conf
├── data
├── logs
└── script
    ├── create_clusterRedis.sh
    └── create_port_Redisconf.sh

5 directories, 9 files

#创建一个端口为7889的redis实例并启动
[root@python2 redis]# sh script/create_port_confRedis.sh 7889 yes
[root@python2 redis]# sh service_7889.sh start
[root@python2 redis]# ps -ef |grep redis
root      11929      1  0 21:54 ?        00:00:00 /export/server/redis/bin/redis-server *:7889 [cluster]
root      11934   1173  0 21:54 pts/0    00:00:00 grep --color=auto redis

#再次查看Redis目录结构
[root@python2 redis]# tree .
.
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof
│   ├── redis-check-rdb
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── conf
│   ├── 7889
│   │   ├── nodes.conf
│   │   └── redis_7889.conf
│   └── redis.conf
├── data
├── logs
│   ├── redis_7889.log
│   └── redis_7889.pid
├── script
│   ├── create_clusterRedis.sh
│   └── create_port_confRedis.sh
└── service_7889.sh

6 directories, 14 files

由此可见,创建redis实例前后,目录结构也发生了变化,而且redis实例也启动成功,但这个只是单节点的,要想创建一个redis分布式集群,还需要执行 create_clusterRedis.sh ip:port,xx,xx,xx,xx,xx yes才可以,不再详细描述!

3、查看RPM包签名到期时间

#查看签名到期时间
#获取到rpm包中的签名ID eb5c386d788b960f
[root@python2 .gnupg]# rpm -qpi /export/rpmbuild/RPMS/x86_64/redis-5.0.9-1.x86_64.rpm
Name        : redis
Version     : 5.0.9
Release     : 1
Architecture: x86_64
Install Date: (not installed)
Group       : System Middleware
Size        : 6280870
License     : BSD
Signature   : RSA/SHA1, Fri 05 Jul 2024 05:02:58 PM CST, Key ID eb5c386d788b960f
Source RPM  : redis-5.0.9-1.src.rpm
Build Date  : Fri 05 Jul 2024 05:02:46 PM CST
Build Host  : python2
Relocations : (not relocatable)
URL         : https://download.redis.io/releases/redis-5.0.9.tar.gz
Summary     : The redis for centos 7 x86_64.
Description : This is redis

#根据ID查看到期时间
[root@python2 .gnupg]# gpg --list-keys  eb5c386d788b960f
pub   4096R/788B960F 2024-07-05 [expires: 2026-07-05]
uid                  rpmbuild (GPG-RPM-KEY) <rootwxd@163.com>
sub   4096R/4CE2423E 2024-07-05 [expires: 2025-07-05]

4、卸载redis-rpm包

卸载也很顺利,没有任何问题

[root@python2 redis]# rpm -qa |grep redis
redis-5.0.9-1.x86_64
[root@python2 redis]# rpm -e redis-5.0.9-1.x86_64
Automatically stopping all Redis services...
Redis data has been backed up to /export/backup/.
userdel: /var/spool/mail/redis not owned by redis, not removing
Redis user has been deleted

至此,Redis-5.0.9版本的rpm包构建完成,并且也成功的部署到了线上,目前已运行了两周,并未发现任何问题


总结

要想看懂这篇文章,必须先把文章顶部引用的链接文章看几遍并读懂它,然后回过头来再看本文章,就会轻松很多,第一个中间件已通过rpmbuild的形式构建完成,勤能补拙,以描述的背景为例,多加练习构造出合适的rpm包,不仅比源码安装方便还更加利于管理,这样的安装方式谁能不爱呢!!!

  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值