本文共 14246 字,大约阅读时间需要 47 分钟。
构建rpm包
自从20多年前开始使用Linux以来,我就一直使用基于rpm的软件包管理器在Red Hat和Fedora Linux上安装软件。 我已经使用了rpm程序本身yum和DNF ,后者是yum的近代产品,用于在Linux主机上安装和更新软件包。 yum和DNF工具是rpm实用程序的包装,它们提供了其他功能,例如查找和安装软件包依赖项的能力。
rpm工具以前用于构建rpm软件包,该功能已删除 ,并且创建了一个新工具 rpmbuild来构建新的rpm。当我开始这个项目时,我发现关于创建rpm软件包的信息很少,但是我设法找到了一本书, Maximum RPM ,可以帮助我弄清楚。 那本书现在已经有些过时了,正如我所发现的绝大多数信息一样。 它也已经绝版,用过的副本价值数百美元。 可免费获得的在线版本,并保持最新状态。 也有指向其他网站的链接,这些网站上有很多有关rpm的文档。 还有哪些其他信息通常是简短的,并且显然假定您已经对该过程有足够的了解。
另外,我发现的每个文档都假定代码需要像在开发环境中那样从源代码进行编译。 我不是开发人员。 我是系统管理员,我们的系统管理员有不同的需求,因为我们不(或不应该)编译用于管理任务的代码。 我们应该使用外壳脚本。 因此,从某种意义上说,我们没有源代码,需要将其编译为二进制可执行文件。 我们拥有的也是一个可执行文件。
在大多数情况下,该项目应以非root用户身份执行。 Rpms绝对不能由root用户构建,而只能由非特权用户构建。 我将指出哪些部分应以root用户身份执行,哪些部分应由非root用户,非特权用户执行。
首先,打开一个终端会话,然后su
到root。 请确保使用-
选项以确保启用了完整的根环境。 我认为sysadmins不应将sudo
用于任何管理任务。 在我的个人博客文章中找到原因: 。
[ student @ testvm1 ~ ] $ su - Password: [ root @ testvm1 ~ ] #
创建一个可用于该项目的学生用户,并为该用户设置密码。
[ root @ testvm1 ~ ] # useradd -c "Student User" student [ root @ testvm1 ~ ] # passwd student Changing password for user student. New password: < Enter the password > Retype new password: < Enter the password > passwd: all authentication tokens updated successfully. [ root @ testvm1 ~ ] #
构建rpm软件包需要rpm-build
软件包,该软件包可能尚未安装。 现在以根用户身份安装。 请注意,此命令还将安装多个依赖项。 该数量可能会有所不同,具体取决于主机上已安装的软件包。 它在我的测试VM上总共安装了17个软件包,这是最小的。
dnf install -y rpm-build
除非另有明确指示,否则该项目的其余部分应以用户学生的身份执行。 打开另一个终端会话,然后使用su
切换到该用户以执行这些其余步骤。 使用以下命令从GitHub下载我为开发目录结构utils.tar准备的tarball:
wget https: // github.com / opensourceway / how-to-rpm / raw / master / utils.tar
该压缩包包括最终rpm将安装的所有文件和Bash脚本。 还有一个完整的规格文件,可用于构建rpm。 我们将详细介绍spec文件的每个部分。
作为用户学生,使用您的主目录作为当前的工作目录(pwd),解压压缩包。
[ student @ testvm1 ~ ] $ cd ; tar -xvf utils.tar
使用tree
命令来验证〜/ development的目录结构以及包含的文件如下所示:
[ student @ testvm1 ~ ] $ tree development / development / ├── license │ ├── Copyright.and.GPL.Notice.txt │ └── GPL_LICENSE.txt ├── scripts │ ├── create_motd │ ├── die │ ├── mymotd │ └── sysdata └── spec └── utils.spec 3 directories, 7 files [ student @ testvm1 ~ ] $
mymotd
脚本创建发送到stdout的“每日消息”数据流。 该create_motd
脚本运行mymotd
脚本,输出到/ etc / MOTD文件重定向。 该文件用于向使用SSH远程登录的用户显示每日消息。
die
脚本是我自己的脚本,将kill
命令包装在一些代码中,这些代码可以找到与指定字符串匹配的正在运行的程序并杀死它们。 它使用kill -9
来确保他们不能忽略kill消息。
sysdata
脚本可以喷出成千上万行有关您的计算机硬件,Linux的安装版本,所有已安装的软件包以及硬盘驱动器的元数据的数据。 我用它来记录某个时间点的主机状态。 以后可以参考。 我曾经这样做是为了维护为客户安装的主机的记录。
您可能需要将这些文件和目录的所有权更改为student.student。 如有必要,请使用以下命令执行此操作:
chown -R student.student development
该树中的大多数文件和目录将通过您在该项目期间创建的rpm安装在Fedora系统上。
rpmbuild
命令需要非常特定的目录结构。 您必须自己创建此目录结构,因为没有提供自动方式。 在主目录中创建以下目录结构:
~ ─ rpmbuild ├── RPMS │ └── noarch ├── SOURCES ├── SPECS └── SRPMS
我们将不会创建rpmbuild / RPMS / X86_64目录,因为该目录是特定于体系结构的64位编译二进制文件。 我们提供的Shell脚本不是特定于体系结构的。 实际上,我们也不会使用SRPMS目录,该目录将包含编译器的源文件。
每个规范文件都有许多部分,具体取决于rpm构建的具体情况,其中一些部分可以忽略或省略。 这个特定的规范文件不是工作所需的最小文件的示例,而是一个打包不需要编译的文件的中等复杂规范文件的很好的示例。 如果需要编译,则将在%build
部分中执行该编译,由于不需要编译,因此在此spec文件中将其省略。
这是规格文件中唯一没有标签的部分。 它包含运行rpm -qi [Package Name]
命令rpm -qi [Package Name]
看到的许多信息。 每个数据都是由标签组成的一行,该标签用于标识它以及用于标签值的文本数据。
############################################################################### # Spec file for utils ################################################################################ # Configured to be built by user student or other non-root user ################################################################################ # Summary: Utility scripts for testing RPM creation Name: utils Version: 1.0.0 Release: 1 License: GPL URL: http: // www.both.org Group: System Packager: David Both Requires: bash Requires: screen Requires: mc Requires: dmidecode BuildRoot: ~ / rpmbuild / # Build with the following syntax: # rpmbuild --target noarch -bb utils.spec
rpmbuild
程序将忽略注释行。 我总是喜欢在此部分添加注释,其中包含创建软件包所需的rpmbuild
命令的确切语法。 Summary标记是软件包的简短描述。 Name,Version和Release标签用于创建rpm文件的名称,如utils-1.00-1.rpm一样。 增加发行号和版本号可以创建可用于更新较旧版本的rpm。
许可证标签定义了发布软件包所依据的许可证。 我总是使用GPL的变体。 指定许可证对于弄清软件包中包含的软件是开放源代码这一事实很重要。 这也是为什么我将许可证和GPL声明包含在将要安装的文件中的原因。
URL通常是项目或项目所有者的网页。 在这种情况下,这是我的个人网页。
Group标记很有趣,通常用于GUI应用程序。 组标记的值确定应用程序菜单中的哪一组图标将包含此程序包中的可执行文件的图标。 Group标记与Icon标记(此处未使用)结合使用,可添加图标和所需信息以将程序启动到应用程序菜单结构中。
Packager标记用于指定负责维护和创建软件包的人员或组织。
Requires语句定义此rpm的依赖性。 每个都是包名。 如果不存在指定的软件包之一,则DNF安装实用程序将尝试将其放在/etc/yum.repos.d中定义的已定义存储库之一中,并进行安装(如果存在)。 如果DNF找不到一个或多个所需的软件包,它将抛出错误,指示缺少哪些软件包并终止。
BuildRoot行指定了顶级目录,在该目录中rpmbuild
工具将在其中找到规格文件,并在构建软件包时在其中创建临时目录。 完成的软件包将存储在我们之前指定的noarch子目录中。 显示用于构建此程序包的命令语法的注释包括–target noarch
选项,该选项定义了目标体系结构。 由于这些是Bash脚本,因此它们与特定的CPU体系结构无关。 如果省略此选项,则构建将针对执行构建的CPU的体系结构。
rpmbuild
程序可以针对许多不同的体系结构,使用--target
选项允许我们在主机上构建特定于体系结构的程序包,该主机具有与执行构建的体系结构不同的体系结构。 因此,我可以在x86_64主机上构建旨在用于i686架构的软件包,反之亦然。
将打包程序名称更改为您自己的名称,将URL更改为您自己的网站(如果有)。
规范文件的%description
部分包含rpm软件包的描述。 它可能很短,也可能包含很多行信息。 我们的%description
部分非常简洁。
% description A collection of utility scripts for testing RPM creation.
%prep
部分是在构建过程中执行的第一个脚本。 在安装软件包期间不会执行此脚本。
该脚本只是一个Bash shell脚本。 它准备构建目录,根据需要创建用于构建的目录,并将适当的文件复制到各自的目录中。 这将包括完整编译所需的源代码(作为构建的一部分)。
$ RPM_BUILD_ROOT目录表示已安装系统的根目录。 在$ RPM_BUILD_ROOT目录中创建的目录是活动文件系统中的标准路径,例如/ user / local / share / utils,/ usr / local / bin等。
就我们的软件包而言,我们没有预编译源,因为我们所有的程序都是Bash脚本。 因此,我们只需将这些脚本和其他文件复制到已安装系统中它们所属的目录中即可。
% prep ################################################################################ # Create the build tree and copy the files from the development directories # # into the build tree. # ################################################################################ echo "BUILDROOT = $RPM_BUILD_ROOT " mkdir -p $RPM_BUILD_ROOT / usr / local / bin / mkdir -p $RPM_BUILD_ROOT / usr / local / share / utils cp / home / student / development / utils / scripts /* $RPM_BUILD_ROOT / usr / local / bin cp / home / student / development / utils / license /* $RPM_BUILD_ROOT / usr / local / share / utils cp / home / student / development / utils / spec /* $RPM_BUILD_ROOT / usr / local / share / utils exit
请注意,此部分末尾的exit语句是必需的。
规范文件的此部分定义了要安装的文件及其在目录树中的位置。 它还指定文件属性以及每个要安装文件的所有者和组所有者。 文件权限和所有权是可选的,但我建议对其进行显式设置,以消除安装时这些属性不正确或模棱两可的可能性。 如果目录不存在,则会在安装过程中根据需要创建目录。
% files % attr ( 0744, root, root ) / usr / local / bin /* % attr ( 0644, root, root ) / usr / local / share / utils /*
在我们的实验室项目的规范文件中,此部分为空。 在这里可以放置在rpm安装期间但在文件安装之前必须运行的所有脚本。
规范文件的这一部分是另一个Bash脚本。 此文件在安装文件后运行。 该部分几乎可以满足您的所有需要,包括创建文件,运行系统命令以及在进行配置更改后重新启动服务以重新初始化它们。 我们的rpm软件包的%post
脚本执行其中一些任务。
% post ################################################################################ # Set up MOTD scripts # ################################################################################ cd / etc # Save the old MOTD if it exists if [ -e motd ] then cp motd motd.orig fi # If not there already, Add link to create_motd to cron.daily cd / etc / cron.daily if [ ! -e create_motd ] then ln -s / usr / local / bin / create_motd fi # create the MOTD for the first time / usr / local / bin / mymotd > / etc / motd
该脚本中包含的注释应使其目的明确。
本部分包含一个脚本,该脚本将在rpm软件包卸载后运行。 使用rpm或DNF删除软件包会删除%files
部分中列出的所有%files
,但不会删除%post
部分创建的文件或链接,因此我们需要在本部分中进行处理。
该脚本通常由清除任务组成,这些清除任务简单地擦除rpm以前安装的文件就无法完成。 对于我们的软件包,它包括删除%post
脚本创建的链接,以及恢复motd文件的原始保存。
% postun # remove installed files and links rm / etc / cron.daily / create_motd # Restore the original MOTD if it was backed up if [ -e / etc / motd.orig ] then mv -f / etc / motd.orig / etc / motd fi
该Bash脚本在rpm构建过程之后执行清理。 以下%clean
部分中的两行删除了rpm-build
命令创建的构建目录。 在许多情况下,可能还需要进行其他清理。
% clean rm -rf $RPM_BUILD_ROOT / usr / local / bin rm -rf $RPM_BUILD_ROOT / usr / local / share / utils
此可选文本部分包含对rpm及其包含的文件的更改的列表。 最新更改记录在本节的顶部。
% changelog * Wed Aug 29 2018 Your Name < Youremail @ yourdomain.com > - The original package includes several useful scripts. it is primarily intended to be used to illustrate the process of building an RPM.
用您自己的姓名和电子邮件地址替换标题行中的数据。
规格文件必须位于rpmbuild树的SPECS目录中。 我发现最容易在该目录中创建指向实际规格文件的链接,以便可以在开发目录中对其进行编辑,而无需将其复制到SPECS目录中。 将SPECS目录设置为pwd,然后创建链接。
cd ~ / rpmbuild / SPECS / ln -s ~ / development / spec / utils.spec
运行以下命令以构建rpm。 如果没有错误发生,则只需花一点时间即可创建rpm。
rpmbuild --target noarch -bb utils.spec
在〜/ rpmbuild / RPMS / noarch目录中检查以确认新的rpm是否存在。
[ student @ testvm1 ~ ] $ cd rpmbuild / RPMS / noarch / [ student @ testvm1 noarch ] $ ll total 24 -rw-rw-r--. 1 student student 24364 Aug 30 10 :00 utils-1.0.0- 1 .noarch.rpm [ student @ testvm1 noarch ] $
以root用户身份安装rpm,以验证其安装正确以及文件安装在正确的目录中。 rpm的确切名称取决于您在Preamble部分中用于标签的值,但是,如果您在示例中使用了这些值,则rpm名称将如以下示例命令中所示:
[ root @ testvm1 ~ ] # cd /home/student/rpmbuild/RPMS/noarch/ [ root @ testvm1 noarch ] # ll total 24 -rw-rw-r--. 1 student student 24364 Aug 30 10 :00 utils-1.0.0- 1 .noarch.rpm [ root @ testvm1 noarch ] # rpm -ivh utils-1.0.0-1.noarch.rpm Preparing... ################################# [100%] Updating / installing... 1 :utils-1.0.0- 1 ################################# [100%]
检查/ usr / local / bin以确保新文件在那里。 您还应该验证是否已创建/etc/cron.daily中的create_motd链接。
使用rpm -q --changelog utils
命令查看更改日志。 使用rpm -ql utils
命令查看软件包安装的文件(在ql
为小写L)。
[ root @ testvm1 noarch ] # rpm -q --changelog utils * Wed Aug 29 2018 Your Name < Youremail @ yourdomain.com > - The original package includes several useful scripts. it is primarily intended to be used to illustrate the process of building an RPM. [ root @ testvm1 noarch ] # rpm -ql utils / usr / local / bin / create_motd / usr / local / bin / die / usr / local / bin / mymotd / usr / local / bin / sysdata / usr / local / share / utils / Copyright.and.GPL.Notice.txt / usr / local / share / utils / GPL_LICENSE.txt / usr / local / share / utils / utils.spec [ root @ testvm1 noarch ] #
取出包装。
rpm -e utils
现在,您将更改规格文件,以要求不存在的软件包。 这将模拟无法满足的依赖关系。 将以下行立即添加到现有的“需要”行下:
Requires: badrequire
生成软件包并尝试安装它。 显示什么消息?
我们使用rpm
命令安装和删除utils
软件包。 尝试使用yum或DNF安装软件包。 您必须与程序包位于同一目录中,或指定程序包的完整路径才能正常工作。
在创建rpm包的基础知识中,我们没有涉及很多标签和几个部分。 下面列出的资源可以提供更多信息。 构建rpm包并不困难; 您只需要正确的信息。 我希望这对您有帮助-我花了几个月的时间自行解决。
我们没有涵盖源代码的构建,但是如果您是开发人员,那么从这一点开始这应该是一个简单的步骤。
创建rpm软件包是成为懒惰的系统管理员并节省时间和精力的另一种好方法。 它提供了一种简单的方法来分发和安装脚本和其他文件,这些文件和其他文件是系统管理员需要在许多主机上安装的。
爱德华·贝利(Edward C.Baily), 最高RPM ,萨姆斯出版,2000年,ISBN 0-672-31105-4
Edward C. Baily, ,更新了在线版本
:此网页列出了大多数可用的rpm在线文档。 它包含许多指向其他网站的链接以及有关rpm的信息。
翻译自:
构建rpm包
转载地址:http://iqdzd.baihongyu.com/