为OpenWrt路由器编译哪吒监控
最近想重新写一套监控系统代替已经使用几年的ServerStatus云探针,在搜索过程中发现了一个现成的轮子哪吒监控完美的符合自己的需求,遂部署到自己的各设备上。但是官方提供的基于mips架构的二进制文件一直提示错误,于是打算自己重新编译一份用于路由器。
编译哪吒监控
Go语言是Google开发的一种静态强类型的编译型语言,天生支持高并发,因此常用于网络通信相关程序的开发之中,比如著名的V2Ray
项目,哪吒监控也是基于Go语言所开发的。此前完全没有接触过Go语言相关的开发工作,但是意料之外的发现编译一个Go语言项目,是如此的轻松,仅需要安装Go语言环境,并不需要类似Java
的Maven
或是JavaScript
的npm
打包工具。
1 |
git clone [email protected]:naiba/nezha.git |
交叉编译至路由器
路由器使用的CPU是基于mips架构的MediaTek MT7621
,进一步的发现Go语言的交叉编译完全不需要任何的交叉编译工具链,配置好环境变量,即可编译出各种平台(Windows,Liunx,macOS)各种架构(x86,arm,mips)下的二进制文件。
1 |
GOOS=linux GOARCH=mips go build cmd/agent/main.go |
这样编译出的文件其大小和行为都和官方提供的二进制文件一致,运行即提示line 1: syntax error: unexpected "("
错误。经过查询发现这个问题多半是架构没有选对,经过再三确认MT7621
的确是mips
架构并不是mips64
架构,于是怀疑是字节序的问题,采用小端模式重新编译,发现产生了不一样的问题。
1 |
GOOS=linux GOARCH=mipsle go build cmd/agent/main.go |
再次查询,MT7621
本身没有FPU(浮点运算器),需要使用软件模拟浮点运算器,于是加入softfloat
编译参数,至此成功编译出MT7621
CPU可运行的二进制文件。
1 |
GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build cmd/agent/main.go |
为二进制文件瘦身
虽然已成功编译出可用的二进制文件,但是其大小有17836KB
,在寸土寸金的32MB闪存的路由器上,其直接占去了一半的空间,因此下一个目标就是为二进制文件瘦身。
1 |
GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "-s -w" cmd/agent/main.go |
为ld
传递-s -w
参数,使生成的二进制文件去除调试信息,产生Release模式下的二进制文件,文件大小立刻缩小了5M,占用12736KB
。加入trimpath
参数,删除二进制文件中的系统文件路径,进一步缩减大小,在x86
架构下减少了约130KB,但是在mips
架构下,并没有缩减任何的大小。
1 |
GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -trimpath -ldflags "-s -w" cmd/agent/main.go |
使用upx工具,进一步压缩二进制文件。最新的3.96
版本在mips
架构下存在bug,压缩后的二进制文件无法运行,而新版本又尚未发布,因此必须回退使用3.95
版本。以下为upx
工具各压缩比下的性能测试。
1 |
upx --best -o nezha-agent main |
参数 | 程序大小 | 压缩比 | 耗时 |
---|---|---|---|
原始程序 | 12736KB | ||
-1 | 5042KB | 60.41% | 2s |
-9 | 4222KB | 67.53% | 15s |
–best | 4031KB | 68.35% | 116s |
总结
提前配置好Go
运行环境,下载upx
压缩工具,不要使用3.96
版本,使用3.95
版本或未来3.96
后的新版本。
1 |
git clone [email protected]:naiba/nezha.git |