当前位置: 首页 > news >正文

rpmbuild打包

目标是把 rpmbuild 的核心概念、标准流程、常见命令、服务类软件打包方式和排错方法串成一份可直接上手的教程。

1. 什么是 RPM 和 rpmbuild

  • RPM:Linux 下常见的软件包格式与底层包管理机制。
  • rpm 命令:负责安装、卸载、查询、校验本地.rpm包。
  • dnf/yum:更上层的包管理工具,负责仓库管理、依赖解析,并最终调用 rpm。
  • rpmbuild:用来把源码、脚本、配置文件、systemd 服务文件等内容构建成 RPM 包。

可以简单理解为:

dnf/yum 负责“拿包并解决依赖” rpm 负责“安装和管理包” rpmbuild 负责“制作包”

2. 先建立正确认知:RPM 包里到底装的是什么

一个 RPM 包通常包含:

  • 可执行文件,如/usr/bin/*
  • 配置文件,如/etc/*
  • 服务文件,如/usr/lib/systemd/system/*.service
  • 文档、license、man 手册
  • 安装/升级/卸载脚本
  • 依赖关系、架构信息、校验信息等元数据

最终哪些文件会进 RPM 包,不是看你复制了什么,而是看%files里声明了什么

  • %install里放进%{buildroot},但没写到%files:不会被打进包
  • 写到了%files,但实际文件不存在:打包会失败

3. rpm 与 dnf/yum 的关系

用户 ↓ dnf / yum ← 自动处理仓库和依赖 ↓ rpm ← 执行本地包安装、查询、卸载 ↓ 文件系统 + RPM 数据库

什么时候优先用哪个

  • 安装本地包做测试rpm -ivhdnf install ./xxx.rpm
  • 正式部署,且希望自动补依赖:优先dnf install
  • 查看包内容、脚本、元数据:用rpm -q*系列命令

4. 安装打包工具

在 RPM 系发行版上安装:

sudodnfinstall-yrpm-build rpmdevtools rpmlint

适用于:

  • RHEL
  • CentOS Stream
  • Fedora
  • openEuler
  • Rocky Linux
  • AlmaLinux
  • 部分麒麟/统信 RPM 环境

说明:rpmdevtools并不是所有 Debian/Ubuntu 环境都适用,本文教程以 RPM 系系统为主。

5. 初始化 rpmbuild 目录结构

执行:

rpmdev-setuptree

默认会在当前用户家目录下生成:

~/rpmbuild/ ├── BUILD/ # 解压源码、执行编译的工作目录 ├── BUILDROOT/ # 模拟安装根目录 ├── RPMS/ # 生成的二进制 RPM 包 ├── SOURCES/ # 源码包、补丁、配置源文件 ├── SPECS/ # .spec 文件 └── SRPMS/ # 生成的源码 RPM 包

后续最常打交道的是:

  • SOURCES/
  • SPECS/
  • RPMS/
  • BUILDROOT/

6.%{buildroot}是什么

%{buildroot}RPM 构建时的虚拟根目录,用来模拟真实系统的/

你在%install阶段不能直接把文件安装到真实系统路径,而是必须先装进%{buildroot},最后再由 rpmbuild 打包。

例如:

%install mkdir -p %{buildroot}/usr/bin install -m 0755 myapp %{buildroot}/usr/bin/

这表示:

  • 构建阶段先把myapp放到临时根目录里
  • 最终用户安装 RPM 后,它才会出现在真实系统的/usr/bin/myapp

为什么一定要这样做

  • 避免构建过程污染当前系统
  • 可以重复构建和检查包内容
  • 能清楚区分“构建机环境”和“安装目标环境”

常见错误

错误写法:

install -m 0755 myapp /usr/bin/

正确写法:

install -m 0755 myapp %{buildroot}/usr/bin/

7..spec文件是什么

.spec是 RPM 打包的核心控制文件。它定义:

  • 包名、版本、依赖、描述
  • 源码从哪里来
  • 怎么解压、怎么编译、怎么安装
  • 最终打哪些文件进包
  • 安装和卸载时需要执行哪些脚本

可以把它理解成 RPM 的“打包配方”。

8..spec文件基本结构

一个最小化的.spec文件通常长这样:

Name: hello-kernel Version: 1.0 Release: 1%{?dist} Summary: A dummy package for learning rpmbuild License: GPL-3.0-or-later Source0: %{name}-%{version}.tar.gz BuildArch: noarch %description A dummy package for learning rpmbuild. %prep %setup -q %build : %install mkdir -p %{buildroot}/usr/share/hello printf 'Hello from kernel!\n' > %{buildroot}/usr/share/hello/message %files /usr/share/hello/message %changelog * Sun May 25 2026 Your Name <you@example.com> - 1.0-1 - Initial package

9..spec中最重要的字段

9.1 头部字段

字段作用
Name包名
Version软件版本
Release打包发布号
Summary简短描述
License许可证
URL项目主页,可选
Source0源码压缩包
BuildRequires构建依赖
Requires运行依赖
BuildArch架构,如x86_64noarch

9.2 常见区段

区段作用
%description详细描述
%prep解压源码、打补丁
%build编译
%install安装到%{buildroot}
%files声明最终进包的文件
%pre安装前脚本
%post安装后脚本
%preun卸载前脚本
%postun卸载后脚本
%changelog变更记录

10. rpmbuild 的标准构建流程

rpmbuild 一般遵循下面这条主线:

准备源码 → %prep → %build → %install → %files 校验 → 生成 RPM

10.1%prep

负责准备源码,一般会解压Source0

%prep %setup -q -n %{name}-%{version}

其中:

  • -q:安静模式
  • -n:指定解压后的顶层目录名

10.2%build

如果需要编译,就在这里执行编译命令:

%build gcc -g -O2 -Wall -o myprogram src/myprogram.c

如果是不需要编译的纯脚本/纯配置包,也可以留空或写:

%build :

10.3%install

把产物安装到%{buildroot}

%install mkdir -p %{buildroot}%{_bindir} install -m 0755 myprogram %{buildroot}%{_bindir}/

10.4%files

列出最终打包的路径:

%files %{_bindir}/myprogram

11. 可以编译,也可以不编译

这是很多人最容易混淆的点。

rpmbuild 只负责执行 spec 里的步骤,并不强制要求你一定要编译。

11.1 场景一:源码编译型打包

适合:

  • C/C++ 程序
  • 需要针对目标平台构建的软件
  • 从源码生成二进制

示例:

%build make %{?_smp_mflags} %install make install DESTDIR=%{buildroot}

11.2 场景二:预编译/脚本型打包

适合:

  • shell/python/perl 脚本
  • 配置文件包
  • 已提前在 CI 中产出的二进制
  • 闭源程序分发

示例:

%build : %install mkdir -p %{buildroot}%{_bindir} install -m 0755 myapp %{buildroot}%{_bindir}/

12. 最小可运行示例:打一个最简单的 RPM 包

12.1 准备源码目录

cd~mkdir-phello-kernel-1.0echo'Hello from kernel!'>hello-kernel-1.0/message

12.2 制作源码包

tar-czf~/rpmbuild/SOURCES/hello-kernel-1.0.tar.gz-C~ hello-kernel-1.0

注意这里的压缩包名和顶层目录名要匹配:

  • 压缩包:hello-kernel-1.0.tar.gz
  • 顶层目录:hello-kernel-1.0/

12.3 编写 spec 文件

保存到~/rpmbuild/SPECS/hello-kernel.spec

Name: hello-kernel Version: 1.0 Release: 1%{?dist} Summary: A dummy package for learning rpmbuild License: GPL-3.0-or-later Source0: %{name}-%{version}.tar.gz BuildArch: noarch %description A dummy package for learning rpmbuild. %prep %setup -q %build : %install mkdir -p %{buildroot}/usr/share/hello install -m 0644 message %{buildroot}/usr/share/hello/message %files /usr/share/hello/message %changelog * Sun May 25 2026 Your Name <you@example.com> - 1.0-1 - Initial package

12.4 开始构建

rpmbuild-bb~/rpmbuild/SPECS/hello-kernel.spec

12.5 成功后产物位置

~/rpmbuild/RPMS/noarch/hello-kernel-1.0-1.noarch.rpm

修正说明:如果BuildArch: noarch,最终包名通常是noarch.rpm,不是x86_64.rpm

12.6 安装验证

sudodnfinstall-y~/rpmbuild/RPMS/noarch/hello-kernel-1.0-1.noarch.rpmcat/usr/share/hello/message

13. 常用 rpmbuild 命令

13.1 构建二进制包

rpmbuild-bbyour-package.spec

13.2 构建源码包

rpmbuild-bsyour-package.spec

13.3 同时构建源码包和二进制包

rpmbuild-bayour-package.spec

13.4 查看已安装包信息

rpm-qiyour-package-namerpm-qlyour-package-namerpm-q--scriptsyour-package-name

13.5 查询某个文件属于哪个包

rpm-qf/path/to/file

13.6 查看 rpm 包内容但不安装

rpm-qplyour-package.rpmrpm-qpiyour-package.rpm

14. 常用宏

含义常见值
%{_topdir}rpmbuild 根目录~/rpmbuild
%{_sourcedir}源文件目录~/rpmbuild/SOURCES
%{_specdir}spec 目录~/rpmbuild/SPECS
%{_builddir}编译目录~/rpmbuild/BUILD
%{_buildrootdir}buildroot 根目录~/rpmbuild/BUILDROOT
%{buildroot}当前包的临时安装根目录动态生成
%{_bindir}可执行文件目录/usr/bin
%{_sbindir}管理命令目录/usr/sbin
%{_unitdir}systemd unit 目录通常是/usr/lib/systemd/system
%{_sysconfdir}配置目录/etc
%{_datadir}数据目录/usr/share

建议优先写宏,不要硬编码路径。

例如:

install -m 0755 myapp %{buildroot}%{_bindir}/ install -m 0644 myapp.service %{buildroot}%{_unitdir}/

15. RPM 安装过程到底发生了什么

执行下面命令时:

sudorpm-ivhpkg.rpm

或:

sudodnfinstall./pkg.rpm

大致流程如下:

1. 读取 RPM 头部信息 2. 检查架构、依赖、签名 3. 执行 %pre 4. 解包并写入文件系统 5. 处理 %config 配置文件策略 6. 更新 RPM 数据库 7. 执行 %post

如果是卸载:

%preun → 删除文件 → %postun

16. 安装/升级/卸载脚本怎么写

服务类软件经常会用到脚本区段。

16.1 安装后脚本%post

%post if [ $1 -eq 1 ]; then systemctl daemon-reload systemctl enable myapp.service >/dev/null 2>&1 || : systemctl start myapp.service >/dev/null 2>&1 || : fi

16.2 卸载后脚本%postun

%postun if [ $1 -eq 0 ]; then systemctl stop myapp.service >/dev/null 2>&1 || : systemctl disable myapp.service >/dev/null 2>&1 || : systemctl daemon-reload fi

16.3$1的常见含义

不同脚本阶段对$1的语义会有差异,但在实际打包里,最常见判断方式是:

  • $1 -eq 1:通常表示安装后首次配置场景
  • $1 -eq 0:通常表示彻底卸载场景

实际项目里如果脚本逻辑比较敏感,建议结合发行版文档和测试结果确认。

17. 配置文件与日志文件要区别处理

17.1 配置文件

如果文件允许用户改动,建议使用:

%files %config(noreplace) /etc/myapp/myapp.conf

这样升级时:

  • 用户改过的配置尽量保留
  • 不会被新包直接覆盖

17.2 日志文件

日志文件一般不建议直接作为普通静态文件打进包,更常见做法是:

  • 由程序自己创建
  • 或通过tmpfiles.d、logrotate、首次启动逻辑创建

如果只是教学演示,也可以在%post中用touch创建:

%post install -d -m 0755 /var/log/myapp >/dev/null 2>&1 || : touch /var/log/myapp/myapp.log || : chmod 0644 /var/log/myapp/myapp.log || :

说明:生产环境更推荐让应用本身或日志系统接管日志文件,而不是在%files里长期维护一个空日志文件。

18. 实战示例:把一个 systemd 服务打成 RPM

下面用你文档里的sdet-monitor作为完整示例。

目标:

  • 安装一个监控程序det-monitor
  • 安装对应的 systemd 服务
  • 安装后自动启用并启动服务
  • 卸载时自动停止并禁用服务

19. 项目目录建议

先准备项目目录:

mkdir-p~/det-monitor/{src,systemd}cd~/det-monitor

目录结构建议如下:

det-monitor/ ├── src/ │ └── det-monitor.c └── systemd/ └── det-monitor.service

修正说明:源码压缩包里通常不必再额外塞一个rpm/目录,只要最终把 spec 复制到~/rpmbuild/SPECS/即可。

20. 编写 systemd 服务文件

文件:systemd/det-monitor.service

[Unit] Description=Monitor for det command execution After=network.target [Service] Type=simple ExecStart=/usr/bin/det-monitor Restart=always RestartSec=5 User=root Group=root StandardOutput=journal StandardError=journal Nice=19 IOSchedulingClass=idle [Install] WantedBy=multi-user.target

说明

  • Restart=always:异常退出后自动重启
  • RestartSec=5:5 秒后重启
  • Nice=19:降低 CPU 调度优先级
  • IOSchedulingClass=idle:尽量减少 I/O 干扰

如果程序不必须以 root 运行,生产环境建议尽量使用专用低权限用户。

21. 编写服务类软件的 spec 文件

文件:~/rpmbuild/SPECS/det-monitor.spec

Name: det-monitor Version: 1.0 Release: 1%{?dist} Summary: Monitor for execution of det command License: GPL-3.0-or-later Source0: %{name}-%{version}.tar.gz BuildRequires: gcc, systemd Requires(post): systemd Requires(preun): systemd Requires(postun): systemd %description This service monitors the execution of the det command. %prep %setup -q -n %{name}-%{version} %build gcc -g -O2 -Wall -o det-monitor src/det-monitor.c %install rm -rf %{buildroot} install -d %{buildroot}%{_bindir} install -d %{buildroot}%{_unitdir} install -m 0755 det-monitor %{buildroot}%{_bindir}/det-monitor install -m 0644 systemd/det-monitor.service %{buildroot}%{_unitdir}/det-monitor.service %files %{_bindir}/det-monitor %{_unitdir}/det-monitor.service %post if [ $1 -eq 1 ]; then systemctl daemon-reload >/dev/null 2>&1 || : systemctl enable det-monitor.service >/dev/null 2>&1 || : systemctl start det-monitor.service >/dev/null 2>&1 || : fi %preun if [ $1 -eq 0 ]; then systemctl stop det-monitor.service >/dev/null 2>&1 || : systemctl disable det-monitor.service >/dev/null 2>&1 || : fi %postun systemctl daemon-reload >/dev/null 2>&1 || : %changelog * Sun May 25 2026 Your Name <you@example.com> - 1.0-1 - Initial package

这个版本相比原文修正了什么

  1. 去掉了把日志文件直接塞进%files的做法
  2. 对 systemd 脚本依赖加了更清晰的Requires(post/preun/postun)
  3. 使用%{_bindir}%{_unitdir}代替硬编码路径
  4. %install前显式rm -rf %{buildroot},避免脏目录残留
  5. 将停止/禁用服务放进%preun,把daemon-reload放进%postun,更符合常见实践

22. 制作标准源码包

源码包必须满足两个要求:

  1. 压缩包文件名与Source0对应
  2. 解压后的顶层目录名与%setup期望一致

在项目目录执行:

cd~/det-monitormkdir-pdet-monitor-1.0cp-asrc systemd det-monitor-1.0/tar-czf~/rpmbuild/SOURCES/det-monitor-1.0.tar.gz det-monitor-1.0rm-rfdet-monitor-1.0

也可以先检查压缩包内容:

tar-tf~/rpmbuild/SOURCES/det-monitor-1.0.tar.gz|head

你应该看到类似:

det-monitor-1.0/ det-monitor-1.0/src/ det-monitor-1.0/src/det-monitor.c det-monitor-1.0/systemd/ det-monitor-1.0/systemd/det-monitor.service

23. 构建 RPM 包

执行:

rpmbuild-ba~/rpmbuild/SPECS/det-monitor.spec

成功后通常会生成:

~/rpmbuild/RPMS/x86_64/det-monitor-1.0-1.x86_64.rpm ~/rpmbuild/SRPMS/det-monitor-1.0-1.src.rpm

注意:这里是x86_64还是aarch64,取决于你的构建机架构以及包本身是否声明为noarch

24. 安装与验证

24.1 安装

sudodnfinstall-y~/rpmbuild/RPMS/*/det-monitor-1.0-1.*.rpm

也可以用:

sudorpm-ivh~/rpmbuild/RPMS/*/det-monitor-1.0-1.*.rpm

24.2 检查服务状态

systemctl status det-monitor.service systemctl is-enabled det-monitor.service

预期:

  • 状态为active (running)或至少已成功启动
  • is-enabled输出enabled

24.3 查看包内容

rpm-qldet-monitorrpm-q--scriptsdet-monitor

25. 卸载与验证

卸载:

sudorpm-edet-monitor

或:

sudodnf remove-ydet-monitor

验证:

rpm-qdet-monitor systemctl status det-monitor.servicels-l/usr/bin/det-monitorls-l/usr/lib/systemd/system/det-monitor.service

预期:

  • 包查询不到
  • 服务单元文件已移除
  • 可执行文件已移除

26. 常见错误与排查方法

26.1File not found%files报错

原因通常是:

  • %install没把文件放进%{buildroot}
  • %files路径写错
  • 目标文件名和实际文件名不一致

检查思路:

find~/rpmbuild/BUILDROOT-typef|sort

26.2%prep阶段解压失败

常见原因:

  • Source0文件名不匹配
  • 压缩包顶层目录名与%setup -n ...不一致

26.3 构建依赖缺失

比如:

error: Failed build dependencies: gcc is needed by xxx

处理:

sudodnfinstall-ygccmakesystemd-rpm-macros

26.4 服务安装后没有启动

检查:

systemctl status det-monitor.service journalctl-udet-monitor.service-xerpm-q--scriptsdet-monitor

26.5 日志或配置文件被覆盖

检查是否正确使用:

  • %config(noreplace)
  • 应用自身日志目录策略
  • 是否误把运行时文件直接打进%files

27. 调试技巧

27.1 检查 spec 质量

rpmlint ~/rpmbuild/SPECS/det-monitor.spec rpmlint ~/rpmbuild/RPMS/*/det-monitor-*.rpm

27.2 查看构建目录

ls-l~/rpmbuild/BUILD/ls-l~/rpmbuild/BUILDROOT/

27.3 查看最终 buildroot 内容

tree ~/rpmbuild/BUILDROOT

27.4 查看包内文件列表

rpm-qpl~/rpmbuild/RPMS/*/det-monitor-*.rpm

27.5 查看安装/卸载脚本

rpm-qp--scripts~/rpmbuild/RPMS/*/det-monitor-*.rpm

28. 最佳实践

28.1 压缩包命名规范

推荐:

<name>-<version>.tar.gz

例如:

det-monitor-1.0.tar.gz

28.2 顶层目录名保持一致

例如压缩包内应是:

det-monitor-1.0/

28.3 能用宏就用宏

不要硬编码:

/usr/bin /usr/lib/systemd/system

推荐:

%{_bindir} %{_unitdir}

28.4 不要在%install中改真实系统

所有写入都应进入%{buildroot}

28.5 区分构建依赖和运行依赖

  • BuildRequires:编译时依赖
  • Requires:安装运行时依赖

28.6 尽量不用 root 做构建

构建阶段通常应在普通用户下执行,安装阶段再使用sudo

28.7 服务包优先考虑 systemd 生命周期

至少要考虑:

  • 安装后daemon-reload
  • 首次安装后enable/start
  • 卸载前stop/disable
  • 卸载后daemon-reload

29. 一份从零到打包成功的最短操作清单

如果你只想快速上手,按下面执行即可。

29.1 初始化环境

sudodnfinstall-yrpm-build rpmdevtools rpmlint rpmdev-setuptree

29.2 准备源码包

mkdir-p~/demo-1.0echo'hello rpm'>~/demo-1.0/READMEtar-czf~/rpmbuild/SOURCES/demo-1.0.tar.gz-C~ demo-1.0

29.3 写 spec

Name: demo Version: 1.0 Release: 1%{?dist} Summary: Simple demo rpm License: MIT Source0: %{name}-%{version}.tar.gz BuildArch: noarch %description Simple demo rpm. %prep %setup -q %build : %install mkdir -p %{buildroot}/usr/share/demo install -m 0644 README %{buildroot}/usr/share/demo/README %files /usr/share/demo/README

保存到:

~/rpmbuild/SPECS/demo.spec

29.4 构建

rpmbuild-bb~/rpmbuild/SPECS/demo.spec

29.5 安装验证

sudodnfinstall-y~/rpmbuild/RPMS/noarch/demo-1.0-1.noarch.rpmrpm-qldemo

30. 总结

你可以把 RPM 打包记成三句话:

  1. **源码、脚本、服务文件先准备好,放进 **SOURCES/
  2. .spec明确描述“怎么解压、怎么编译、怎么安装、打哪些文件”
  3. rpmbuild构建,再用rpm/dnf安装验证

真正掌握 rpmbuild,关键不是死记命令,而是理解下面这条链路:

Source0 → %prep → %build → %install → %{buildroot} → %files → RPM 包 → rpm/dnf 安装
http://www.jsqmd.com/news/890686/

相关文章:

  • 2026年大连全屋定制工厂怎么选?源头直营vs中间商,一文看透鑫盛祥、欧派、索菲亚与本地竞品 - 精选优质企业推荐官
  • 【IEEE出版,IEEE Xplore, EI, Scopus】第七届能源电力与自动化工程国际学术会议(ICEPAE 2026) - 爱搞科研的小刘
  • 华为“τ”计划:打破算力墙,重新定义AI应用开发的“新基建”
  • 2026武汉性价比高的财税公司推荐 十大代理记账公司排名 - 品牌优企推荐
  • MIDI软件系列分享
  • 3天掌握开源视频播放器:打造专属观影空间的完整攻略
  • 内蒙古钢材厂家推荐|赤峰腾云钢铁现货足配送快供货稳定 - 深度智识库
  • 2026年昆明AI全网推广与短视频运营服务商深度评测:GEO优化与本地化获客完全指南 - 年度推荐企业名录
  • 从达沃斯人到马尼拉女人:全球化浪潮下的身份认同与技术翻译新范式
  • 量子卷积神经网络:利用对称性提升小样本图像分类泛化能力
  • 深圳奢侈品首饰回收实测:2026 最新行情,热门款报价表 - 奢侈品回收测评
  • 2026年大连全屋定制工厂怎么选?源头直营vs中间商,一文读懂鑫盛祥、欧派、索菲亚、尚品宅配、瑞和五大品牌 - 精选优质企业推荐官
  • 3分钟解决B站缓存视频播放难题:m4s-converter完全指南
  • Postman与JMeter选型指南:功能验证vs性能压测的决策逻辑
  • SpecPathGNN:基于通路中心图神经网络的可解释生物网络分析
  • 中微SC8F072/SC8P062代码生成工具
  • 对比不同模型在创意生成任务上的效果Taotoken模型广场选型指南
  • C语言实战:差分攻击原理与三轮DES密钥恢复
  • Windows 11终极瘦身指南:3分钟免费恢复系统极速体验
  • 为什么视频中FrameCount / FrameRate ≠ Duration?
  • 鞍山黄金回收选长悦诚信老店让市民卖金省心又放心 - 专业黄金回收
  • 旺宏代理商-Macronix代理商-旺宏nor/nand flash代理商-深圳市微效电子有限公司
  • 如何在5分钟内用SillyTavern打造你的AI聊天伴侣:从零开始完整指南
  • 音频运放与电阻测试平台:模块化设计与性能对比实战
  • ESP32-S3-ZERO天线改造:从信号不稳到增益提升10dB的实战指南
  • 小样本类增量学习:基于角度间隔的ILAR方法原理与复现实践
  • 基于PoE供电与NTP同步的嵌入式网络时钟设计与实现
  • B站视频下载终极指南:3分钟掌握BilibiliDown完整使用技巧
  • 2026年昆明企业AI全网推与短视频运营完全选购指南:从GEO优化到私域转化的本地化破局方案 - 年度推荐企业名录
  • 内网渗透作战地图:从信息收集到域控沦陷的实战逻辑链