最近工作需要用rpm把相关文件打包并拷贝到目的目录,网上很多教程写的都很详细,但是实践起来有很多迷惑的地方,所以用一篇文章来记录一些心得体会,让打包变得简单一些。
本文不涉及太深奥的打包技巧,主要是常用的部分。
参考文章:https://blog.csdn.net/get_set/article/details/53453320
如何构建 RPM 包 - Linux中国的文章 - 知乎 https://zhuanlan.zhihu.com/p/47868584
操作系统:CentOs7
安装rpm:yum install rpm
安装rpmbuild:yum install rpm-build
注:如果你的机器是离线的,需要下载离线安装包,这里给出rpmbuild的安装方式(最重要)
rpm-build:https://pkgs.org/download/rpm-build
rpm-build安装的方式是 rpm -ivh rpm-build-4.11.3-40.el7.x86_64.rpm,如果提示缺少依赖,需要忽略依赖,加上--nodeps选项
rpm -ivh rpm-build-4.11.3-40.el7.x86_64.rpm --nodeps
安装成功
创建rpm目录:
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}默认位置
宏代码
名称
用途
~/rpmbuild/SPECS
%{_specdir}
Spec 文件目录
保存 RPM 包配置(.spec)文件
~/rpmbuild/SOURCES
%{_sourcedir}
源代码目录
保存源码包(如 .tar 包和所有 patch 补丁)
~/rpmbuild/BUILD
%{_builddir}
构建目录
源码包被解压至此,并在该目录的子目录完成编译
~/rpmbuild/BUILDROOT
%{_buildrootdir}
最终安装目录
保存 %install 阶段安装的文件
~/rpmbuild/RPMS
%{_rpmdir}
标准 RPM 包目录
生成/保存二进制 RPM 包
~/rpmbuild/SRPMS
%_srcrpmdir
源代码 RPM 包目录
生成/保存源码 RPM 包(SRPM)
通过实际例子来学习整个打包的流程,这个东西刚开始的时候不了解感觉很迷糊,掌握了之后发现其实就是一套流程,跟着流程走下来就行了。
我们来做一个自动安装jdk的rpm包
首先下载linux版本jdk安装包
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
注意不要直接下载.rpm ,下载tar.gz
把压缩包拷贝到~/rpmbuild/SOURCES 目录下
先给出完整的spec文件
Name: jdk Version: 1.0 Release: 1%{?dist} Summary: build jdk rpm packet Group: jdk License: GPL Source0: jdk-8u231-linux-x64.tar.gz BuildRequires: gcc Requires: gcc BuildRoot: ~/rpmbuild/ %description build a jdk rpm packet,by using this packet to install jdk automated %prep mkdir -p %{buildroot}/usr/local/java %setup -c -b 0 exit %build %install cp -r jdk1.8.0_231 %{buildroot}/usr/local/java %files %defattr(-,root,root,-) /usr/local/java/* %exclude %doc %pre %post echo 'export JAVA_HOME=/usr/local/java/jdk1.8.0_231' >> /etc/profile echo 'export JRE_HOME=/usr/local/java/jdk1.8.0_231/jre' >> /etc/profile echo 'export CLASSPATH=.:/usr/local/java/jdk1.8.0_231/lib:/usr/local/java/jdk1.8.0_231/jre/lib' >> /etc/profile echo 'export PATH=/usr/local/java/jdk1.8.0_231/bin:$PATH' >> /etc/profile %preun %postun %changelog %clean rm -rf %{buildroot} rm -rf %{_builddir}/*1.进入SPECS目录下创建jdk.spec文件
注:不要用windows下的编辑器编写,因为windows下换行符是'\r\n',会报错的,推荐用notepad++或者vim
.spec文件是rpm打包的依据,所以主要的任务也是编写这个文件
spec文件的组成
Name: 软件名称 Version: 软件版本 Release: 发布次数 如: 1%{?dist} Summary: 软件说明 Group: 软件分组 License: 授权模式,例如 GPL,即自由软件 URL: 源码包的URL地址,可随意填写 Source0: 源码包,可指定多个,下面可用%{SOURCE0}变量引用 BuildRoot: 编译过程中的中间存档目录,考虑到多用户的环境,一般定义为: %{_tmppath}/%{name}-%{version}-%{release}-root, 后面可使用$RPM_BUILD_ROOT 方式引用 BuildArch: 平台 %{_arch} BuildRequires: 编译过程依赖的工具 Requires: 打包生成的rpm包安装时所依赖的软件包 %description 说明文档 %prep 准备部分,比如创建目录,解压源码包等,可使用%setup内部函数 %build 在BUILD目录编译,可使用%configure内部函数,或者其他编译工具,如 cmake, perl等 %install 安装到BUILDROOT虚拟目录 %clean 清理文件 %files 将指定的文件添加到rpm包中,文档类型可用%doc,配置文件可 用%config %changelog 更新记录.格式: 第一行 "* 日期 作者 " 第二行 "- 更新内容" 最终的生成的rpm名称: {Name}-{Version}-{Relesae}- {BuildArch}.rpm文件中很多用不到是可以省略的,下面主要介绍常用的部分
2.编写spec文件
首先切换到~/rpmbuild/SPECS目录下 vim jdk.spec ,系统会自动生成文件格式,当然也可以自己写
前面部分一般是固定的,名字版本号分组和摘要是自己根据情况写,license一般默认GPL,release这样写就可以了
Source0部分是我们的压缩包的名字,URL一般放链接,这里不写,BuildRequires是打包过程中需要的环境,Requires是安装rpm包需要的环境,如果没有会报错,description是描述信息
Name: jdk Version: 1.0 Release: 1%{?dist} Summary: build jdk rpm packet Group: jdk License: GPL Source0: jdk-8u231-linux-x64.tar.gz BuildRequires: gcc Requires: gcc BuildRoot: ~/rpmbuild/ %description build a jdk rpm packet,by using this packet to install jdk automated2.1 预处理 %prep
%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。 %patch0 -p0 打第1个补丁,0表示利用当前相对路径名称 %pacth1 -p2 打第2个补丁,2表示忽略补丁文件第一层目录 %patch 0 使用第0个补丁文件,相当于%patch ?p 0。 %patch -s 不显示打补丁时的信息。 %patch -T 将所有打补丁时产生的输出文件删除。这里我们选择
%prep mkdir -p %{buildroot}/usr/local/java #%{buildroot}是~/rpmbuild/BUILDROOT,在下面创建一个目录 %setup -c -b 0 #解压 exit由于解压缩后默认会cd到 目录 name-version下,如果没有-c选项通常会报错
执行完这一步会在~/rpmbuild/BUILD目录下创建一个jdk-1.0目录
里面才是我们需要的jdk目录
注:exit不能缺少
2.2 %build
这个阶段是编译阶段,如果有什么程序需要编译或者需要make在这个阶段执行即可
2.3 %install
安装阶段,这个阶段做的工作就是把相关文件拷贝到%{buildroot}也就是~/rpmbuild/BUILDROOT/jdk-1.0-1.el7.centos.x86_64目录下,将来安装rpm包的时候会自动安装到%{buildroot}后面的目录下
例如我们生成rpm包过程中会把jdk拷贝到%{buildroot}/usr/local/java目录下,将来安装的时候会自动把jdk拷贝到/usr/local/java目录下
2.4 %files
这个阶段是定义拷贝文件的权限,如果你需要拷贝可执行程序,那么需要赋予可执行权限
%defattr(-,root,root,-)中间两个是用户和组,-表示原来文件什么权限,后来也是什么权限
如果原来文件没有可执行权限,安装rpm包需要可执行,那么就改成%defattr(0755,root,root,-)
2.5 %exclude
这个是列出不放到rpm包里的文件,如果文件不存在但是写了就会报错,如果有一些文件没写但是没拷贝也会报错
2.6 %doc
这个是列出不复制到%{buildroot}目录下的文件
2.7 %pre
这个阶段是安装rpm包前会先执行的内容,一般是环境相关的内容
2.8 %post
这个阶段是安装rpm包后执行的内容,一般把文件拷贝完成后需要执行一些操作来处理
这里我们就是编辑java的环境变量,让它生效
2.9 %preun
卸载rpm包前做的工作
2.10 %postun
卸载rpm包后做的工作
2.11 %changelog
这个地方写日志,日志格式不符合标准会报错
2.12 %clean
这个阶段是生成rpm包后执行的清理工作,一般是把中间产生的文件,主要是在BUILDROOT和BUILD目录下的文件清除掉
3.打包
通过下面命令进行打包,如果出现错误可以看到是哪一条脚本命令执行失败,定位并处理
rpmbuild -bb test.spec4.安装rpm包
rpm -ivh --nodeps --force 包名 #这样是忽略依赖的强制安装输入 java -version可以看到
5.查看拷贝的文件
rpm -ql 包名 #注意包名的后缀 .rpm 不能要通过该命令就可以看到安装rpm包会拷贝哪些文件到哪些目录下
6.查看rpm包头部信息
rpm -qpi 包名.rpm7.卸载rpm包
rpm -e 包名 #后缀 .rpm 不要其实掌握了之后就会发现跟着流程从头到尾执行一遍就行,每个阶段该干什么,里面的内容都是linux命令,这里有点类似于脚本,命令都是可以执行的。