2026-01-14 · 架构
32
架构 · 2026-01-14

从零开始打 DEB 和 RPM 包:Go 程序打包实战指南

为什么要打包

你写了一个 Go 程序,想让别人在 Linux 上用。最简单的方法是扔个二进制文件,但这有几个问题:

打成 DEB 或 RPM 包能解决这些问题。用户可以用包管理器安装、升级、卸载,系统会自动处理依赖和配置文件。

本文用一个 Go 的 HelloWorld 程序,演示如何从零开始打 DEB 和 RPM 包。所有命令都可以直接执行。

准备示例程序

先写一个简单的 Go 程序。创建 hello.go

package main

import "fmt"

func main() {
    fmt.Println("Hello from packaged binary!")
}

编译成静态二进制文件:

CGO_ENABLED=0 go build -o hello hello.go

CGO_ENABLED=0 确保不依赖 libc,打出来的包可以在任何 Linux 发行版上跑。

测试一下:

./hello
# 输出: Hello from packaged binary!

DEB 打包实战

DEB 包本质上是一个 ar 归档,包含两部分:控制信息和程序文件。

构建目录结构

创建打包目录:

mkdir -p hello-deb/DEBIAN
mkdir -p hello-deb/usr/local/bin

DEBIAN 目录存放控制文件,usr/local/bin 是程序的安装路径。

把二进制文件复制进去:

cp hello hello-deb/usr/local/bin/
chmod 755 hello-deb/usr/local/bin/hello

创建 control 文件

control 文件描述包的元数据。创建 hello-deb/DEBIAN/control

Package: hello
Version: 1.0.0
Section: utils
Priority: optional
Architecture: amd64
Maintainer: Your Name <your@email.com>
Description: A simple hello world program
 This is a demo package for learning DEB packaging.

几个关键字段:

打包

dpkg-deb 打包:

dpkg-deb --build hello-deb

会生成 hello-deb.deb 文件。改个更规范的名字:

mv hello-deb.deb hello_1.0.0_amd64.deb

命名格式是 包名_版本_架构.deb

安装测试

在 Debian/Ubuntu 系统上安装:

sudo dpkg -i hello_1.0.0_amd64.deb

运行:

hello
# 输出: Hello from packaged binary!

查看已安装的包信息:

dpkg -s hello

卸载:

sudo dpkg -r hello

RPM 打包实战

RPM 打包依赖一个 .spec 文件,所有配置都写在里面。

准备构建环境

RPM 有固定的目录结构。创建:

mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

这些目录的作用:

准备源码包

把程序打成 tar.gz:

mkdir hello-1.0.0
cp hello hello-1.0.0/
tar czf hello-1.0.0.tar.gz hello-1.0.0/
mv hello-1.0.0.tar.gz ~/rpmbuild/SOURCES/

RPM 打包习惯从源码开始,所以要先打个源码包。

创建 spec 文件

创建 ~/rpmbuild/SPECS/hello.spec

Name:           hello
Version:        1.0.0
Release:        1%{?dist}
Summary:        A simple hello world program

License:        MIT
Source0:        %{name}-%{version}.tar.gz

%description
This is a demo package for learning RPM packaging.

%prep
%setup -q

%install
mkdir -p %{buildroot}/usr/local/bin
install -m 755 hello %{buildroot}/usr/local/bin/hello

%files
/usr/local/bin/hello

%changelog
* Tue Jan 14 2026 Your Name <your@email.com> - 1.0.0-1
- Initial package

关键字段解释:

打包

rpmbuild 打包:

rpmbuild -ba ~/rpmbuild/SPECS/hello.spec

-ba 同时生成二进制包和源码包。生成的文件在:

ls ~/rpmbuild/RPMS/x86_64/
# hello-1.0.0-1.el8.x86_64.rpm

文件名包含 el8(表示 RHEL 8)或 fc36(表示 Fedora 36),这是 %{?dist} 宏自动加的。

安装测试

在 RHEL/CentOS/Fedora 系统上安装:

sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/hello-1.0.0-1.*.x86_64.rpm

运行:

hello
# 输出: Hello from packaged binary!

查看包信息:

rpm -qi hello

卸载:

sudo rpm -e hello

两种方式对比

维度
DEB
RPM

配置文件
多个小文件(control, postinst 等)
一个 spec 文件

依赖声明
Depends: python3, curl
Requires: python3, curl

构建工具
dpkg-deb(轻量)
rpmbuild(需要完整环境)

源码处理
可选
强制打 tar.gz

架构命名
amd64, arm64
x86_64, aarch64

DEB 更灵活:不强制要源码包,可以直接打二进制包。适合快速打包。

RPM 更规范:spec 文件集中管理所有配置,大型项目更清晰。企业环境常用。

实战建议

  1. 静态编译:Go 程序用 CGO_ENABLED=0,避免 libc 版本问题
  2. 版本号规范:用 major.minor.patch 格式,比如 1.2.3
  3. 测试安装:在干净的容器里测试,确保依赖声明正确
  4. 自动化:写个 Makefile 或 shell 脚本,一键打包

一个简单的 Makefile 示例:

VERSION = 1.0.0
BINARY = hello

.PHONY: build deb rpm

build:
    CGO_ENABLED=0 go build -o $(BINARY) hello.go

deb: build
    mkdir -p hello-deb/DEBIAN
    mkdir -p hello-deb/usr/local/bin
    cp $(BINARY) hello-deb/usr/local/bin/
    cp debian-control hello-deb/DEBIAN/control
    dpkg-deb --build hello-deb
    mv hello-deb.deb hello_$(VERSION)_amd64.deb

rpm: build
    mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
    mkdir hello-$(VERSION)
    cp $(BINARY) hello-$(VERSION)/
    tar czf hello-$(VERSION).tar.gz hello-$(VERSION)/
    mv hello-$(VERSION).tar.gz ~/rpmbuild/SOURCES/
    cp hello.spec ~/rpmbuild/SPECS/
    rpmbuild -ba ~/rpmbuild/SPECS/hello.spec

运行:

make deb  # 打 DEB 包
make rpm  # 打 RPM 包

常见问题

Q: 能不能一个包同时支持 DEB 和 RPM?

不行。得分别打包。但可以用 FPM 工具,它可以从一个配置生成多种格式的包。

Q: 我的程序依赖其他包怎么办?

在 control 或 spec 文件里声明。比如依赖 Python:

安装时包管理器会自动安装依赖。

Q: 打出来的包能跨发行版吗?

如果是静态编译的 Go 程序,理论上可以。但不同发行版的目录结构和依赖包名可能不同,最好分别打包。

Q: 生产环境怎么管理自己打的包?

搭建私有软件仓库。DEB 用 aptlyreprepro,RPM 用 createrepo

以上就是从零开始打 DEB 和 RPM 包的完整流程。用一个 HelloWorld 程序演示了最核心的步骤,实际项目可能需要处理配置文件、systemd 服务等,但基本原理是一样的。

目录 最新
← 左侧翻上一屏 · 右侧翻下一屏 · 中间唤出菜单