最近工作需要用rpm把相关文件打包并拷贝到目的目录,网上很多教程写的都很详细,但是实践起来有很多迷惑的地方,所以用一篇文章来记录一些心得体会,让打包变得简单一些。
本文不涉及太深奥的打包技巧,主要是常用的部分。
参考文章:
如何构建 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 automated
2.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.spec
4.安装rpm包
rpm -ivh --nodeps --force 包名 #这样是忽略依赖的强制安装
输入 java -version可以看到
5.查看拷贝的文件
rpm -ql 包名 #注意包名的后缀 .rpm 不能要
通过该命令就可以看到安装rpm包会拷贝哪些文件到哪些目录下
6.查看rpm包头部信息
rpm -qpi 包名.rpm
7.卸载rpm包
rpm -e 包名 #后缀 .rpm 不要
总结
其实掌握了之后就会发现跟着流程从头到尾执行一遍就行,每个阶段该干什么,里面的内容都是linux命令,这里有点类似于脚本,命令都是可以执行的。