github workflow构建哪吒探针FreeBSD安装包
之前写了关于如何在serv00/ct8机器上一键安装哪吒探针的内容,这里主要分享下如何构建这种运行在serv00/ct8
这种FreeBSD
操作系统上的哪吒探针面板二进制安装包。
当然,也可以直接了当的在github上查看https://github.com/vfhky/nezha-build的源代码,也可以直接下载代码构建出来的可用于serv00/ct8
这种FreeBSD
主机的哪吒面板安装包。
一、背景
由于哪吒官方没有提供FreeBSD
的dashboard面板安装包,所以如果想在serv00/ct8
上使用就得先自己构建一个。
可以看到serv00_ct8_nezha项目最初的几个版本(也是哪吒探针V0版本期间),是在安装期间直接拉取官方源代码构建出来的:即在serv00/ct8
机器安装探针面板时,会先用命令go build -ldflags="-s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=${version_num}"
构建得到安装包然后再安装。
这样带来的问题就是每次安装或者升级
dashboard面板时都会消耗较长时间,所以在24年10月做了优化:
- 创建一个新的github工程nezha-build使用 workflow 来构建哪吒面板
FreeBSD
安装包; - 原有github工程serv00_ct8_nezha解耦后就只需从 nezha-build 下载
FreeBSD
包安装即可。
二、开启CGO
哪吒探针dashboard面板是go语言开发的,但是使用了go-sqlite3
驱动,所以在交叉编译的时候必须得设置CGO_ENABLED=1
,否则就会得到go-sqlite3 requires cgo to work
的错误:
三、交叉编译的困局
在开启CGO
的前提下,最初nezha-build工程尝试在github workflow中使用 Ubuntu 环境,然后使用交叉编译工具链(如 Clang、musl-tools)来构建 FreeBSD amd64 二进制文件。但实际操作中,却遇到了各种棘手的难题:主要是缺少FreeBSD C
头文件。
3.1 使用clang编译
先贴一下workflow核心代码:
- name: Build
uses: goreleaser/goreleaser-action@v6
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 1
CC: /usr/bin/clang
with:
distribution: goreleaser
version: "~> v2"
workdir: nezha
args: build --single-target --clean --skip=validate
然后运行workflow报错:
│ build failed: failed to build for freebsd_amd64_v1: exit status 1: # runtime/cgo
│ In file included from _cgo_export.c:3:
│ /usr/include/stdlib.h:25:10: fatal error: 'bits/libc-header-start.h' file not found
│ target: freebsd_amd64_v1
Error: The process '/__t/goreleaser-action/2.6.1/x64/goreleaser' failed with exit code 1
原因:在 Go runtime 尝试编译其 C 代码部分时,会默认使用当前 Ubuntu 系统中的 glibc 头文件,导致编译器尝试包含 bits/libc-header-start.h,从而引发错误。
3.2 使用musl-tools编译
先贴一下workflow核心代码:
- name: Install dependencies
run: |
apt-get install -y clang lld musl-tools
.......................
- name: Build
uses: goreleaser/goreleaser-action@v6
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 1
CC: /usr/bin/musl-gcc # Use musl-gcc symlink
LDFLAGS: "-static" # Crucial: Static linking with musl
然后运行workflow报错:
│ build failed: failed to build for freebsd_amd64_v1: exit status 1: # runtime/cgo
│ gcc_freebsd_amd64.c:7:10: fatal error: sys/signalvar.h: No such file or directory
│ 7 | #include <sys/signalvar.h>
│ | ^~~~~~~~~~~~~~~~~
│ compilation terminated.
│ target: freebsd_amd64_v1
Error: The process '/__t/goreleaser-action/2.6.1/x64/goreleaser' failed with exit code 1
原因:同样的,sys/signalvar.h 是 FreeBSD 特有的系统头文件,它在 Ubuntu 系统中并不存在。尽管我尝试使用 musl-gcc 作为交叉编译器,但是 Go runtime 自身的 C 代码仍然会尝试使用 Ubuntu 系统中的头文件,导致编译器无法找到 sys/signalvar.h。
3.3 困局
通过多次构建,我发现即使使用了clang 、musl-tools 和其它交叉编译工具链,仍然无法在 Ubuntu 环境下成功构建 FreeBSD amd64 二进制文件。
四、解决方案:vmactions/freebsd-vm
上述问题归根结底是由于构建环境不一致导致的。我在 Ubuntu 环境中尝试构建 FreeBSD 程序,虽然使用了交叉编译工具,但是 Go runtime 仍然会受到 Ubuntu 系统库的影响。因此,我需要一个真正的 FreeBSD 环境来进行构建。
vmactions/freebsd-vm 正是为此而生,它可以在 GitHub Actions 工作流程中启动一个真实的 FreeBSD 虚拟机,提供一个与目标环境完全一致的构建环境,从而彻底解决交叉编译带来的各种问题。
vmactions/freebsd-vm
的大致原理:依赖于 QEMU 进行虚拟化,并通过 SSH 进行远程控制,以实现自动化任务。
1、在Ubuntu中运行 QEMU,然后创建 FreeBSD 虚拟机;
2、使用预构建的 FreeBSD 磁盘镜像。从源代码中的freebsd-vm/conf/14.1.conf可以看到诸如
OVA_LINK="https://github.com/vmactions/freebsd-builder/releases/download/v${BUILDER_VERSION}/freebsd-${VM_RELEASE}.qcow2.zst"
3、使用SSH公私钥连接 FreeBSD 虚拟机,上传哪吒探针dashboard面板源码并构建。
五、总结
可以看到在相较于开启CGO
后交叉编译构建哪吒探针面板FreeBSD
安装包的复杂,使用vmactions/freebsd-vm
提供的真实FreeBSD构建环境可以很简单的实现。
最后,大家可以在 https://github.com/vfhky/nezha-build 查看实现的源代码。也可以直接下载构建好的哪吒探针dashboard面板(FreeBSD
版本),目前设置每天8点、16点、24点拉取官方最新代码进行构建,以便serv00和ct8主机一键安装哪吒探针V1版本工程能下载和安装到最新的探针面板。
Comments »