跨平台交叉编译FreeBSD版的Filebeat

交叉编译

Go是一种很好的语言,虽然有很多很坑的方面,但也是有很多突出的优点,比如goroute,以及可以编译成目标指令运行。

最关键的是它的交叉编译真是太方便了……

在任何支持的平台上编译其它平台的目标执行文件,只需要这样一句:

env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build

其中GOOS可以支持:linux, freebsd, openbsd, macos, windows等,GOARCH支持:i386, amd64, arm。不过因为CGO功能不支持跨平台,所以交叉编译时必须关闭。

之前我有一个需要部署在windows上的程序,就一直是靠着在linux下编译好后再部署到windows上去实现的。

filebeat和FreeBSD

虽然我已经在家里的FreeBSD上装了Docker,可以用docker来跑filebeat,但是还有两台VPS是没条件装Docker的,所以还是需要原生的filebeat去跑,但是官方并没有提供FreeBSD版下载的。

我常常说:Windows是一个善于制造别的系统上不存在的问题的OS。

其实很多时候FreeBSD也是,但相对来说,只要是开源的东西,问题总还是可以解决的。只是麻烦一点而已,需要编译一下罢了。

然而我又不想在家里机器上装个go环境,毕竟能省点事就省点事。那就交叉编译喽,反正手上的Mac正好有现成的go环境。

因为我的环境里,GOPATH被设置为 ~/go ,为了避免编译时找不到module,就直接在这个路径下搞了:

cd ~/go/src/github.com
mkdir elastic
git clone https://github.com/elastic/beats.git
cd beats
git checkout v6.4.1
cd filebeat
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 make

等待一会就编译完成了,在当前路径下会生成一个 filebeat 可执行文件,COPY到FreeBSD试试:

filebeat version
# filebeat version 6.4.1 (amd64), libbeat 6.4.1 [37b5f2d2a20f2734b2373a454b4b4cbb2627e841 built 2018-10-22 06:40:03 +0000 UTC]

成功。

2020-02-06 补充

在编译6.8.x时发生了新的问题:

../vendor/github.com/docker/docker/pkg/system/mknod.go:12:22: cannot use dev (type int) as type uint64 in argument to syscall.Mknod

这是../vendor/github.com/docker/docker/pkg/system/mknod.go文件里的一个BUG,参考FreeBSD的Bug 236131的补丁修改后解决:

-	return syscall.Mknod(path, mode, dev)
+	return syscall.Mknod(path, mode, uint64(dev))

类似的问题发生在编译linux arm64版本时:

../libbeat/common/file/stderr_other.go:30:9: undefined: syscall.Dup2

解决方案来自官方论坛的帖子Cannot make filebeat for aarch64,修改../libbeat/common/file/stderr_other.go文件:

 import (
        "os"
-       "syscall"
+       "golang.org/x/sys/unix"
 )

-       return syscall.Dup2(int(toFile.Fd()), 2)
+       return unix.Dup2(int(toFile.Fd()), 2)

成功解决。

推送到[go4pro.org]