译者:MjSeven

在 Linux 上测试软件时,我使用各种架构的服务器,例如 Intel、AMD、Arm 等。当我分配了一台满足我的测试需求的 Linux 机器,我仍然需要执行许多步骤:

1. 下载并安装必备软件

2. 验证构建服务器上是否有新的测试软件包

3. 获取并设置依赖软件包所需的 yum 仓库

4. 下载并安装新的测试软件包(基于步骤 2)

5. 获取并设置必需的 SSL 证书

6. 设置测试环境,获取所需的 Git 仓库,更改配置,重新启动守护进程等

7. 做其他需要做的事情

用脚本自动化

这些步骤非常常规,以至于有必要对其进行自动化并将脚本保存到中央位置(例如文件服务器),在需要时可以在此处下载脚本。为此,我编写了 100-120 行的 Bash shell 脚本,它为我完成了所有配置(包括错误检查)。这个脚本通过以下方式简化了我的工作流程:

1. 配置新的 Linux 系统(支持测试的架构)

2. 登录系统并从中央位置下载自动化 shell 脚本

3. 运行它来配置系统

4. 开始测试

学习Go语言

我想学习Go 语言有一段时间了,将我心爱的 Shell 脚本转换为 Go 程序似乎是一个很好的项目,可以帮助我入门。它的语法看起来很简单,在尝试了一些测试程序后,我开始着手提高自己的知识并熟悉 Go 标准库。

我花了一个星期的时间在笔记本电脑上编写 Go 程序。我经常在我的 x86 服务器上测试程序,清除错误并使程序健壮起来,一切都很顺利。

直到完全转换到 Go 程序前,我继续依赖自己的 shell 脚本。然后,我将二进制文件推送到中央文件服务器上,以便每次配置新服务器时,我要做的就是获取二进制文件,将可执行标志打开,然后运行二进制文件。我对早期的结果很满意:

$wgethttp://file.example.com//bins/prepnode

$chmod+x./prepnode

$./prepnode

然后,出现了一个问题

第二周,我从资源池中分配了一台新的服务器,像往常一样,我下载了二进制文件,设置了可执行标志,然后运行二进制文件。但这次它出错了,是一个奇怪的错误:

$./prepnode

bash:./prepnode:cannot execute binaryfile:Execformat error

$

起初,我以为可能没有成功设置可执行标志。但是,它已按预期设置:

$lsl prepnode

rwxrxrx.1root root2640529Dec1605:43prepnode

发生了什么事?我没有对源代码进行任何更改,编译没有引发任何错误或警告,而且上次运行时效果很好,因此我仔细查看了错误消息format error

我检查了二进制文件的格式,一切看起来都没问题:

$fileprepnode

prepnode:ELF64bit LSB executable,x8664,version1(SYSV),statically linked,notstripped

我迅速运行了以下命令,识别所配置的测试服务器的架构以及二进制试图运行的平台。它是 Arm64 架构,但是我编译的二进制文件(在我的 x86 笔记本电脑上)生成的是 x86-64 格式的二进制文件:

$unamem

aarch64

脚本编写人员的编译第一课

在那之前,我从未考虑过这种情况(尽管我知道这一点)。我主要研究脚本语言(通常是 Python)以及 Shell 脚本。在任何架构的大多数 Linux 服务器上都可以使用 Bash Shell 和 Python 解释器。总之,之前一切都很顺利。

但是,现在我正在处理 Go 这种编译语言,它生成可执行的二进制文件。编译后的二进制文件由特定架构的指令码或汇编指令组成,这就是为什么我收到格式错误的原因。由于 Arm64 CPU(运行二进制文件的地方)无法解释二进制文件的 x86-64 指令,因此它抛出错误。以前,shell 和 Python 解释器为我处理了底层指令码或特定架构的指令。

Go的交叉编译

我检查了 Golang 的文档,发现要生成 Arm64 二进制文件,我要做的就是在运行go build命令编译 Go 程序之前设置两个环境变量。

GOOS指的是操作系统,例如 Linux、Windows、BSD 等,而GOARCH指的是要在哪种架构上构建程序。

$envGOOS=linux GOARCH=arm64 go buildo prepnode_arm64

构建程序后,我重新运行file命令,这一次它显示的是 ARM AArch64,而不是之前显示的 x86。因此,我在我的笔记本上能为不同的架构构建二进制文件。

$fileprepnode_arm64

prepnode_arm64:ELF64bit LSB executable,ARM aarch64,version1(SYSV),statically linked,notstripped

我将二进制文件从笔记本电脑复制到 ARM 服务器上。现在运行二进制文件(将可执行标志打开)不会产生任何错误:

$./prepnode_arm64h

Usageof./prepnode_arm64:

cCleanexisting installation

nDonotstarttestrun(defaulttrue)

sUsestage environment,defaultisqa

vEnableverbose output

其他架构呢?

x86 和 Arm 是我测试软件所支持的 5 种架构中的两种,我担心 Go 可能不会支持其它架构,但事实并非如此。你可以查看 Go 支持的架构:

$ go tool distlist

Go 支持多种平台和操作系统,包括:

◈ AIX

◈ Android

◈ Darwin

◈ Dragonfly

◈ FreeBSD

◈ Illumos

◈ JavaScript

◈ Linux

◈ NetBSD

◈ OpenBSD

◈ Plan 9

◈ Solaris

◈ Windows

要查找其支持的特定 Linux 架构,运行:

$ go tool distlist|greplinux

如下面的输出所示,Go 支持我使用的所有体系结构。尽管 x86_64 不在列表中,但 AMD64 兼容 x86-64,所以你可以生成 AMD64 二进制文件,它可以在 x86 架构上正常运行:

$ go tool distlist|greplinux

linux/386

linux/amd64

linux/arm

linux/arm64

linux/mips

linux/mips64

linux/mips64le

linux/mipsle

linux/ppc64

linux/ppc64le

linux/riscv64

linux/s390x

处理所有架构

为我测试的所有体系结构生成二进制文件,就像从我的 x86 笔记本电脑编写一个微小的 shell 脚本一样简单:

!/usr/bin/bash

archs=(amd64 arm64 ppc64le ppc64 s390x)

forarchin${archs[@]}

do

envGOOS=linux GOARCH=${arch}go buildo prepnode_${arch}

done

$fileprepnode_*

prepnode_amd64:ELF64bit LSB executable,x8664,version1(SYSV),statically linked,GoBuildID=y03MzCXoZERH0EwAAYI/p909FDnk7xEUo2LdHIyo/V2ABa7X_rLkPNHaFqUQ6/5p_q8MZiR2WYkA5CzJiF,notstripped

prepnode_arm64:ELF64bit LSB executable,ARM aarch64,version1(SYSV),statically linked,GoBuildID=qHCCtLv__jVOcdcOpA/CywRwDz9LN2Wk_fWeJHt/K43P5tU2mzlWJa0noGN/SEev9TJFyvHdKZnPaZgb,notstripped

prepnode_ppc64:ELF64bit MSB executable,64bitPowerPCorcisco7500,version1(SYSV),statically linked,GoBuildID=DMWfc1QwOGIq2hxEzL_u/UE9CIvkIMeNC_ocW4ry/r7NcMATXatoXJQz3yUO/xzfiDIBuUxbuiyaw5Goq,notstripped

prepnode_ppc64le:ELF64bit LSB executable,64bitPowerPCorcisco7500,version1(SYSV),statically linked,GoBuildID=C6qCjxwO9s63FJKDrv3f/xCJa4E6LPVpEZqmbF6B4/Mu6T_ORdxvLavn1Gyq/AWR1pK1cLz9YzLSFt5eU,notstripped

prepnode_s390x:ELF64bit MSB executable,IBM S/390,version1(SYSV),statically linked,GoBuildID=faC_HDe1_iVq2XhpPD3d/7TIv0rulE4RZybgJVmPz/o_SZW_0iS0EkJJZHANxx/zuZgo79Je7zAs3v6Lxuz,notstripped

现在,每当配置一台新机器时,我就运行以下wget命令下载特定体系结构的二进制文件,将可执行标志打开,然后运行:

$wgethttp://file.domain.com//bins/prepnode_

$chmod+x./prepnode_arch>

$./prepnode_arch>

为什么?

你可能想知道,为什么我没有坚持使用 shell 脚本或将程序移植到 Python 而不是编译语言上来避免这些麻烦。所以有舍有得,那样的话我不会了解 Go 的交叉编译功能,以及程序在 CPU 上执行时的底层工作原理。在计算机中,总要考虑取舍,但绝不要让它们阻碍你的学习。

via:https://opensource.com/article/21/1/go-cross-compiling

作者:Gaurav Kamathe选题:lujun9972译者:MjSeven校对:wxy