rpmbuild打包rpm

  • Post author:
  • Post category:其他




一、rpmbuild及rpm



  1. rpm









rpm命令



是RPM软件包的管理工具。rpm原本是Red Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功能强大方便,因而广受欢迎。逐渐受到其他发行版的采用。RPM套件管理方式的出现,让Linux易于安装,升级,间接提升了Linux的适用度。


  1. rpm优点:


    • 包管理系统简单,通过几个命令就可以实现包的安装、升级、卸载。

      安装速度比源码包快的多。

    • 缺点:

      经过编译,不能看到源代码,功能选择不如源码灵活。依赖性强。




  2. rpmbuild













rpmbuild用于构建二进制和源代码软件包。




二、rpmbuild安装

$ yum install rpmbuild


如果上述方法无法找到该系统对应的rpmbuild版本导致安装失败,可使用下面方法

$ yum list |grep rpm-build 查找合适的rpm-build包
$ yum install -y rpm-build.x86_64


然后还需要安装rpmdevtools

$ yum install rpmdevtools 
$ rpmdev-setuptree

此时rpmbuild就安装完毕了,可以查看rpmbuild工作目录

$ rpmbuild --showrc | grep topdir





目录名





作用





BUILD





你要打包的文件将会在这里编译(编译rpm包的临时目录)





BUILDROOT





在虚拟安装(make install)的目录(编译后生成的软件临时安装目录)





RPMS





存放生成的二进制的rpm包(生成的可安装的rpm安装包所在目录)





SOURCES





你要编译的源码包会被copy到这里(所有源代码和补丁文件的存在目录)





SPECS





你执行的spec文件会被copy到这里(存放SOEC文件的目录)





SRPMS





软件最终的rpm源码格式存放路径











三、rpmbuild详解




-bp 只作准备 (解压与打补丁)




-bc 准备并编译




-bi 编译并安装




-bl 检验文件是否齐全




-ba 编译后做成*.rpm和src.rpm




-bb 编译后做成*.rpm





-bs 只做成*.src.rpm



更具体的用法说明





Build options with [ <specfile> | <tarball> | <source package> ]:
*建立包的选项有:[ 从文件<specfile>建立 |从 <tarball>包建立 |从 <source package>包建立]
*从文件<specfile>建立

-bp build through %prep (unpack sources and apply patches) from <specfile>
* -bp 从<specfile>文件的%prep段开始建立(解开源码包并打补丁)
-bc build through %build (%prep, then compile) from <specfile>
*-bc 从<specfile>文件的%build
-bi build through %install (%prep, %build, then install) from <specfile>

-bl verify %files section from <specfile>
*检查<specfile>文件的%files段
-ba build source and binary packages from <specfile>
*建立源码和二进制包
-bb build binary package only from <specfile>
*只建立二进制包
-bs build source package only from <specfile>
*只建立源码包

*rpmbuild的其他使用项

--buildroot=DIRECTORY override build root
*确定以root目录建立包
--clean remove build tree when done
*完成打包后清除BUILD下的文件目录
--nobuild do not execute any stages of the build
*不进行BUILD的阶段
--nodeps do not verify build dependencies
*不检查建立包时的关联文件
--nodirtokens
generate package header(s) compatible with (legacy) rpm[23] packaging

--rmsource remove sources when done
*完成打包后清除sources
--rmspec remove specfile when done
*完成打包后清除specfile
--short-circuit skip straight to specified stage (only for c,i)
*跳过
--target=CPU-VENDOR-OS override target platform
                 *确定包的最终使用平台



四、spec文件详解

生成rpm除了源码外,最重要的就是懂得编写.spec脚本。rpm建包的原理其实并不复杂,可以理解为按照标准的格式整理一些信息,包括:软件基础信息,以及安装、卸载前后执行的脚本,对源码包解压、打补丁、编译,安装路径和文件等。

########################## 关键字 ##############################
Summary:   ELK(elasticsearch+logstash+kibana+filebeat) Server	
						#软件包的内容概要
Name:      elk          			#软件包的名称,后面可使用%{name}的方式引用 
Version:   1.0.0				#版本号
Release:   1 					#发布序列号,也就是第几次制作rpm后面可使用%{release}引用
License:   GPL					#许可,GPL还是BSD等(一般为GPL)
Packager:  RPMBuild			#打包者的信息
Group:     Applications/System	#软件分组,建议使用标准分组
BuildRoot: /					#这个是安装或编译时使用的“虚拟目录”,该参数非常重要,因为在生成rpm的过程中,执行make install时就会把软件安装到上述的路径中,在打包的时候,同样依赖“虚拟目录”为“根目录”进行操作(即%files段)。后面可使用$RPM_BUILD_ROOT 方式引用。
BuildRequires:  gcc,make                        #制作过程中用到的软件包
URL:						#软件的主页
PATCH						#补丁源码,可使用Patch1、Patch2等标识多个补丁,使用%patch0或%{patch0}引用
Provides:  src					#指明本软件一些特定的功能,以便其他rpm识别
Prefix: %{_prefix} 				#这个主要是为了解决今后安装rpm包时,并不一定把软件安装到rpm中打包的目录的情况。这样,必须在这里定义该标识,并在编写%install脚本的时候引用,才能实现rpm安装时重新指定位置的功能
Prefix: %{_sysconfdir} 			#这个原因和上面的一样,但由于%{_prefix}指/usr,而对于其他的文件,例如/etc下的配置文件,则需要用%{_sysconfdir}标识
Build Arch:					#指编译的目标处理器架构,noarch标识不指定,但通常都是以/usr/lib/rpm/marcros中的内容为默认值
Requires:  /bin/sh  /usr/bin/getent /usr/sbin/useradd /usr/sbin/userdel
						#该rpm包所依赖的软件包名称,可以用>=或<=表示大于或小于某一特定版本
Source0:        %{name}-%{version}.tar.gz   
						#定义用到的source,也就是你的源码,如果没有源码,则不需要声明词宏变量
%define _rpmfilename %%{NAME}-%%{VERSION}.%%{ARCH}.rpm


########################## spec脚本主体 ##############################
%prep 			          #预处理脚本
%setup -n %{name}-%{version}      #把源码包解压并放好,通常是从/usr/src/asianux/SOURCES里的包解压到/usr/src/asianux/BUILD/%{name}-%{version}中。一般用%setup -c就可以了,但有两种情况:一就是同时编译多个源码包,二就是源码的tar包的名称与解压出来的目录不一致,此时,就需要使用-n参数指定一下了。

%patch 				  #打补丁, 通常补丁都会一起在源码tar.gz包中,或放到SOURCES目录下。一般参数为:%patch -p1 使用前面定义的Patch补丁进行,-p1是忽略patch的第一层目录%Patch2 -p1 -b xxx.patch 打上指定的补丁,-b是指生成备份文件#将需要需要打包的文件从BUILD 文件夹中拷贝到BUILDROOT文件夹下。

◎补充一下 
引用
%setup 不加任何选项,仅将软件包打开。 
%setup -n newdir 将软件包解压在newdir目录。 
%setup -c 解压缩之前先产生目录。 
%setup -b num 将第num个source文件解压缩。 
%setup -T 不使用default的解压缩操作。 
%setup -T -b 0 将第0个源代码文件解压缩。 
%setup -c -n newdir 指定目录名称newdir,并在此目录产生rpm套件。 
%patch 最简单的补丁方式,自动指定patch level。 
%patch 0 使用第0个补丁文件,相当于%patch ?p 0。 
%patch -s 不显示打补丁时的信息。 
%patch -T 将所有打补丁时产生的输出文件删除。


%configure 			  #这个不是关键字,而是rpm定义的标准宏命令。意思是执行源代码的configure配置
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行 ,使用标准写法,会引用/usr/lib/rpm/marcros中定义的参数。
另一种不标准的写法是,可参考源码中的参数自定义,例如:
引用
CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}

%build 				  #开始构建包
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make的工作 ,常见写法:
引用
make %{?_smp_mflags} OPTIMIZE="%{optflags}"
都是一些优化参数,定义在/usr/lib/rpm/marcros中

%install 			  #开始把软件安装到虚拟的根目录中
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make install的操作。这个很重要,因为如果这里的路径不对的话,则下面%file中寻找文件的时候就会失败。 常见内容有:
%makeinstall 这不是关键字,而是rpm定义的标准宏命令。也可以使用非标准写法:
引用
make DESTDIR=$RPM_BUILD_ROOT install
或
引用
make prefix=$RPM_BUILD_ROOT install

需要说明的是,这里的%install主要就是为了后面的%file服务的。所以,还可以使用常规的系统命令:
引用
install -d $RPM_BUILD_ROOT/
cp -a * $RPM_BUILD_ROOT/

%clean 				  #清理临时文件
通常内容为:
引用
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
rm -rf $RPM_BUILD_DIR/%{name}-%{version}

※注意区分$RPM_BUILD_ROOT和$RPM_BUILD_DIR:
$RPM_BUILD_ROOT是指开头定义的BuildRoot,而$RPM_BUILD_DIR通常就是指/usr/src/asianux/BUILD,其中,前面的才是%file需要的。 

%pre 				  #rpm安装前执行的脚本

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

%preun 				  #rpm卸载前执行的脚本

%postun 			  #rpm卸载后执行的脚本

%files 				  #定义那些文件或目录会放入rpm中
这里会在虚拟根目录下进行,千万不要写绝对路径,而应用宏或变量表示相对路径。 如果描述为目录,表示目录中除%exclude外的所有文件。
%defattr (-,root,root) 指定包装文件的属性,分别是(mode,owner,group),-表示默认值,对文本文件是0644,可执行文件是0755

%exclude 			  #列出不想打包到rpm中的文件
※小心,如果%exclude指定的文件不存在,也会出错的。 
%changelog 			  #变更日志

注:关于上述的spec详解参(chao
偷笑
)考(xi
偷笑
)了前辈的血汗之作   https://www.cnblogs.com/SQL888/p/5776442.html 膜拜!!!!



五、s




pec实例


下面是我在实战中编写的.spec , 上述中的大部分其实并没有用到 , 整体来讲比较简单,如果有错误的地方望大佬不吝赐教.

大概思路就是:将ELKF的四个rpm包整合为一个rpm包,并且覆盖一些初始配置文件,在卸载@postrun中卸载四个rpm包并且删除相关数据目录.

Summary:   ELK(elasticsearch+logstash+kibana+filebeat) Server
Name:      ELK
Version:   1.0.0
Release:   1
License:   GPL
Packager:  RPMBuild
Group:     Applications/System          
BuildRoot: /
Provides:  src
Requires:  /bin/sh  /usr/bin/getent /usr/sbin/useradd /usr/sbin/userdel
AutoReqProv: no

%define _rpmfilename %%{NAME}-%%{VERSION}.%%{ARCH}.rpm

%description
Boog ELK Log analysis system.

%post            #rpm安装后执行的脚本
echo "after rpm install(update)..."
install_elasticsearch(){
	echo "########### begin installing elasticsearch ###########"
	rm -f /var/lib/rpm/.rpm.lock
	es=`rpm -qa | grep elasticsearch`
	if [ `rpm -qa | grep elasticsearch |wc -l` -ne 0 ];then
	echo -e "ERROR: elasticsearch has been installed on this server,the packet_list: $es"
	else
	# install begin
	rpm -ivh /home/elk_install_temp/rpms/elasticsearch-6.1.1.rpm 
	# 设置elasticsearch java环境变量配置
	sed -i "s%\#JAVA_HOME=%JAVA_HOME=$JAVA_HOME%g" /etc/sysconfig/elasticsearch
	# 更改数据目录
	cp -f /home/elk_install_temp/template/elasticsearch.yml /etc/elasticsearch/
	chown -R elasticsearch:elasticsearch /etc/elasticsearch/elasticsearch.yml
	chown -R elasticsearch:elasticsearch /data/log
	chown -R elasticsearch:elasticsearch /data/lib
	#设置开机自启动
	/sbin/chkconfig --add elasticsearch
	fi
	echo "Run 'service elasticsearch start' to start the elasticsearch service"
	echo "###########If the elasticsearch startup failed,Please read '/etc/elasticsearch/remark.txt' for help!!###########"
}
install_kibana(){
	echo "############## begin installing kibana ###############"
	kb=`rpm -qa | grep kibana`
	if [ `rpm -qa | grep kibana |wc -l` -ne 0 ];then
	echo -e "ERROR: kibana has been installed on this server,the packet_list: $kb"
	else
	# install begin
	rpm -ivh /home/elk_install_temp/rpms/kibana-6.1.1-x86_64.rpm
	cp -f /home/elk_install_temp/template/kibana.yml /etc/kibana/
	#设置开机自启动
	/sbin/chkconfig --add kibana
	fi
	echo "Run 'service kibana start' to start the kibana service"
}
install_filebeat(){
	echo "############# begin installing filebeat ##############"
	fb=`rpm -qa | grep filebeat`
	if [ `rpm -qa | grep filebeat |wc -l` -ne 0 ];then
	echo -e "ERROR: filebeat has been installed on this server,the packet_list: $fb"
	else
	# install begin
	rpm -ivh /home/elk_install_temp/rpms/filebeat-6.1.1-x86_64.rpm
	cp -f /home/elk_install_temp/template/filebeat.yml /etc/filebeat/
	#设置开机自启动
	/sbin/chkconfig --add filebeat
	fi
	echo "Run 'service filebeat start' to start the filebeat service"
}
install_logstash(){
	echo "############## begin installing logstash #############"
	lt=`rpm -qa | grep logstash`
	if [ `rpm -qa | grep logstash |wc -l` -ne 0 ];then
	echo -e "ERROR: logstash has been installed on this server,the packet_list: $lt"
	else
	# install begin
	rpm -ivh /home/elk_install_temp/rpms/logstash-6.1.1.rpm
	#覆盖配置文件
	cp -f /home/elk_install_temp/template/logstash-simple.conf /etc/logstash/conf.d/
	#生成logstash启动脚本
	/usr/share/logstash/bin/system-install /etc/logstash/startup.options sysv
	#设置开机自启动
	/sbin/chkconfig --add logstash
	fi
	#服务启动
	/etc/init.d/logstash start
	initctl stop logstash
	echo "Run 'initctl start logstash' to start the logstash service"
}
#执行安装
install_elasticsearch
install_kibana
install_filebeat
install_logstash
################### remove elk install temp ####################
rm -rf /home/elk_install_temp
rm -rf /var/elk_install_temp


%clean
rm -rf %{BuildRoot} 


%preun
%postun           #rpm安装后执行的脚本
if [ $1 = 0 ]; then
	rm -f /var/lib/rpm/.rpm.lock
	##################### begin uninstall elasticsearch ######################
	echo "begin uninstall elk"
	es=`rpm -qa elasticsearch`
	if [ $es ];then
	service elasticsearch stop
	rpm -e $es
	rm -rf /data/lib/elasticsearch
	rm -rf /data/log/elasticsearch
	rm -rf /usr/share/elasticsearch
	fi
	echo 'elasticsearch has been uninstall!'
	######################## begin uninstall logstash ########################
	ls=`rpm -qa logstash`
	if [ $ls ];then
	echo $ls
	/etc/init.d/logstash stop
	#防止logstash 未被成功关闭导致用户无法删除以至于logstash卸载失败
	lsid=`ps aux | grep  logstash | grep -v grep| awk '{print $2}'`
	if [ ! $lsid ]; then  
	  echo "logstash is stop!"  
	else 
	  kill -9 $lsid 
	  echo 'logstash is about to be closed.....'
	fi 
	rpm -e $ls
	rm -rf /etc/init.d/logstash /etc/rc.d/init.d/logstash /etc/logstash /etc/default/logstash
	rm -rf /var/log/logstash /var/log/logstash-std* /var/lib/logstash
	rm -rf /usr/share/logstash
	fi
	echo 'logstash has been uninstall!'
	######################### begin uninstall filebeat #######################
	fb=`rpm -qa filebeat`
	if [ $fb ];then
	echo $fb
	service filebeat stop
	rpm -e $fb
	fi
	echo 'filebeat has been uninstall!'
	######################### begin uninstall kibana #########################
	ki=`rpm -qa kibana`
	if [ $ki ];then
	echo $ki
	service kibana stop
	rpm -e $ki
	fi
	echo 'kibana has been uninstall!'
	###################### remove elk install temp ###########################
	#rm -rf /home/elk_install_temp
	#rm -rf /var/elk_install_temp
fi


%pre
echo $JAVA_HOME
if [ ! $JAVA_HOME ];then
	echo 'ERROR:请先安装java并配置java相关环境'
	exit 0
fi
mkdir -p /data/lib/elasticsearch /data/log/elasticsearch
	
	
%files           #定义那些文件或目录会放入rpm中(这里是BUILDOROOT/name-version/下的源码和配置文件)
/home/elk_install_temp/.elk-release
/home/elk_install_temp/rpms/*
/home/elk_install_temp/template/*
/etc/elasticsearch/remark.txt
%defattr(-,root,root)



版权声明:本文为boog14原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。