走出舒适区,我了解了 Go 的交叉编译功能。

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

  1. 下载% q y u 8 x n . P并安装必备软件
  2. 验证构建服务器上是否有新的测试软件包
  3. 获取并设置依赖软件包所需的 yum 仓库
  4. 下载并安m J S # f装新的测试软件d [ U G : J S包(基于步骤 2)
  5. 获取并设置必需的 SSL 证书
  6. 设置测试0 I V P 1环境,获取所需的 Git 仓库,更改配置,重新启动守护进程等
  7. 做其他需要E w a做的事情

用脚本自动化

这些步骤非常常规,以至于有必要对其进行自动化并将N w G H u /脚本保存到中央位置(E j ! c & { G Y O例如文件服务器)^ | z \ P D 8 F,在需要时可以在此处下载脚本。为此,我编写了 100-120 行的 Bash shell 脚本,它为我完成了所有配置(包括错误检查)。这个脚本通过以下方式简化了c \ 5 N 6 S ( e ?我的工作流程:

  • 配置新的 Linux 系统(支持测试的架构)
  • 登录系统并从中央位置下载自动化 shell 脚Y 4 N
  • 运行它来配置系统
  • 开始测试

学习 Go 语言

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

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

直到完全转C B E V B R v换到 Go+ % / J W 程序前,我继续依赖自己的 shellX 8 V R 脚本。然后,我G i ^ _ E H y .将二进制文件推送到中央文件服务器上,以便每次配置新服务器时,我要做的就是获取二进制文件,将可执行J 3 B标志打开,然后运行二进制文件。, r * S ~ K我对早期4 Q M z X 9 z – )的结果很满意:

  1. $wge) b a r = C j : `thttp://file.example.com/<myuser>/bins/prepnode
  2. $chmod+x./prepnode
  3. $./prepnode

然后,出现了一个问题

第二周,我L 8 x u 9 i从资源池中分配了一o , A K 7 b \ c台新的服务器,像往常一样,我下载了二进制文件,设置了可执行标志,然后运行二进制文件q * H j w。但这次它出错了,是一个奇怪的错误:

  1. $.) $ X ~ 0/prepnode
  2. bash:./prepnode:cannotexecutebinaryfile:Execformaterror
  3. $

起初,我V o \ – 9以为可能] W # u + 9 $没有成功设置Q _ ~ r ? 5 c T可执行标志。但是,它已按预期设置:

  1. $ls-lprepnode
  2. -rwxr-xr-x.1rootroot2640529Dec1605:43prepnode

发生了X 4 – % q g什么事?我没有对源代{ S m ] ^ c O码进行任何更改,编译没有引发任何错误或y ; @ F U 8 & e警告,而且上次运行时效N + \ \ 3 a X果很好,因此% w 4 v我仔细查看了错误消息 format error。

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

  1. $fileprepnode
  2. prepnode:ELF64-bitLSBexecutable,x86-64,version1(SYSV),staticallylinked,notstripped

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

  1. $uname-m
  2. aarch64

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

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

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

Go 的交叉编译

我检查了 Golang 的文档,发现要生成 Arm6? ] x 8 o d a G h4 二进制文件,我要做的就是在运行 go buA ( T u xil* 9 r a 1d 命令编译 Go 程序之前设置两个环境变量。

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

  1. $envGOOS=linuxGOARCH=arm64gobuild-op5 _ s { z ] q | mrepnode_arm64

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

  1. $fileprepnode_arm64
  2. prepn\ V \ : J P zode_arm64:ELF64-bitLSBexecutable,ARMaarch64,version1(SYSV),staticallylink4 2 C l E q Ded,notstripped

我将二进制文件从笔记本电脑复制到 ARM 服务器上} g s b o。现在运行二进制文件(将可e B x B O \ 4 ~执行标志打开)不会产生任何错误:

  1. $./prepnode_arR 4 W v U r s $m64-h
  2. Usageof./prepnode_arm64:
  3. -cCleanexistinginstallat7 S q 0 H kion
  4. -nDonotstarttestrun(defaulttrue)
  5. -sh C F ! ) o X ; dUsestageenvironment,defaultisqa
  6. -vEnableverboseo0 Q 2 qutput

其他架构呢?

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

  1. $got: S - Y = f %ooldistlist

Go 支持多种平台和操作p 5 P \ R k n系统,包括:

  • AIX
  • Android
  • Darwin
  • Dragonfly
  • FreeBSD
  • Illumos
  • JavaScripta u – + S p ? y 7
  • Linux
  • NetBSD
  • OpenBSD
  • Plan 9
  • So] – 6 j z { 3 8laris
  • Windows

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

  1. $gotooldistlist|greplinux

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

  1. $g/ G r G m P : Dotooldistlist|greplinux
  2. linux/386
  3. linux/amd64
  4. linux/arm
  5. linux$ A @/arm64
  6. linux/mips
  7. linux/mips64
  8. linux/mips64le
  9. linux/mipsle
  10. linux/ppct g E S W64
  11. linux/ppc64le
  12. linux/riscv64
  13. linux/s390x

处理所有架构

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

  1. #!/usU Q m X } w ! r rr/bin/bash
  2. archs=(amd64arm64ppc64leppc64s390x)
  3. forarchin${archs[@]}
  4. do
  5. envGOOS=lJ d d ) + I C k sinuxGOARCH=${arch}gobuild-oprepnode_${arch}
  6. done
  1. $fileprepnode_*
  2. prepnd : * 4ode_amd64:ELF64-bitL0 b \ D p ? c lSBexecutable,x86-64,version1(SYSV),% ( &static6 x r t L \ @allylinked,G` 2 4 g D G Z l soq q * j V ? ,BuildID=y03MzCXoZY # q {ERH-0EwAAYI/p909FDnk7xEUo2LdHIyo/V2ABa7X_rLkPNHaFqUQ6/, 3 L ] P p5p_q8MZiR2WYkA5C] | 3zJih i j a O n 9 EF,R ] d d c M / _ cnotstripped
  3. prepnode_$ v 3 j . R K Q Uarm64:ELF64-bitLSBexecutable,A- ( b t s W M , nRMaarch64,version1(SYSV),staticallylinked,GoBuildID=q-H-CCtLv__jVOcdcOpA/CywRwDz9LNC 8 P + 2 : ^ C2Wk_fWeJHt/K4-3P5tU2mzlWJa0noGN/d u c fSEev9TJFyvHdKZnPaZgb,notstripped
  4. prepnode_ppc64:ELF64-bitMSBexecutable,64-bitD { t @ 2 CPowerPCorcisco7500,version1(SYSV),stab i R / Bticallylinked,GoBuildID=DMWfc1QwOGIq2hxEzL_u/UE-9Cx m $ Y 6 d ~IvkIMeNC_ocW4ry/r-7NcMATXatoXJQz3yUO/xzfiDIBuUxbuiyaw5Goq,notstripped
  5. prepnode_ppc6A . V R D 5 & R 04le:ELF64-bitLSBexecutabc ! tle,64-bitPowerPCorcisco7500,versi9 4 s (onP 5 % ! z W1(SYSV),staticallylinked,GoBuildID=C6qCjxwO9sA K 763FJKDrv3f/xCJa4E6LPVB P 5 r npEZqmbF6B4/Mu6T_, \ qOR-dx-vLavn1Gyq/AWR1pK1cLz9YzLSFt5eU,notstripped
  6. prepnode_s390x:ELF64-biU ^ 0 j c 4 GtMSBexecutable,IBMS/390,version1(SYSV),staticallylinked,GoBuildID=faC_HDe1_iVq2XhpPD3d/7TIv0rulE4RZybgJVmPz/o_SZW_0iS0EkJJZHAN| l . N Z |xx/zuZgo79Je7zAs3v6Lxuz,notstripped

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

  1. $wgethttp://file.domain.com/<myuser>/bins/prepnode_&lO : bt;arch>
  2. $chmod+x./prepnode_<arch>
  3. $./prepnode_<arch| * 3 5 f y Y \>

为什么?

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

【责任编辑:未丽燕 TEL:(010)68476606】

点赞 0

发表回复

您的电子邮箱地址不会被公开。