踩坑launchpad编译go程序错误分析

732 阅读2分钟

1. 问题说明

在公司生产环境中,通过launchpad平台推送go源码程序,在编译过程中出现failed报错!!!

sbuild-nonexistent.png

2. 分析

2.1 思路一

排除了源码包在本地环境编译正常的情况。 通过launchpad平台 buildlog日志发现 创建目录 permission denied 被权限拦截。 目前所拥有的是个人账号,猜测权限可能比较低,没有权限。 于是找到公司launchpad维护人员,给出的反馈是:“目前launchpad平台是以普通用户进行安装, 没有办法进行提权。看报错描述是要创建/sbuild-nonexistent目录没权限”

2.2 思路二

目前日志中,有参考价值的只有 “failed to initialize build cache at /sbuild-nonexistent/.cache/go-build” 这条日志。 以找报错,找源头的思想。 锁定了go build 这个范围, 该程序主要将go源码通过go build 编译成二进制可执行文件。

接下来具体分析了 go build 编译动作后到底做了什么操作 ???

首先通过 go build -x 参数对 go build 编译动作进行打印输出

go-build-x.png

go build 会在编译源码之前, 先将go源码文件中所用到的静态库进行记录,然后在go work工作区目录下进行编译成统一_pkg_.a静态库,作为依赖。

图中标红的区域, 也是在launchpad中报错的关键。 go build 编译器用builddid检查文件清单和导入依赖,对比现有静态库和所有源文件修改时间来判断源码是否变化,以此来决定是否需要对包进行重新编译。go build 默认机制,将生成的buildid存放在 /tmp/test02/.cache/go-build go cache 缓存目录下。

调研了go编译环节的机制,通过go GOCACHE 环境变量可以来控制 go cache缓存目录的路径。如果未指定go GOCACHE 环境变量,默认cache目录是所属用户家目录下 .cache/go-build

通过推送launchpad调试包排查,发现go GOCACHE 环境变量是默认家目录

launchpad-go-cache.png

再次找到launchpad 维护人员, 沟通了这个问题。 得到的反馈是:“launchpad 以普通用户编译,没有家目录的概念,按照这个机制来相当于在根目录下创建,会存在权限不足。”

了解了launchpad 机制后, 现在主要的问题是将编译go程序时,将go buildid生成的临时文件,绕开/sbuild-nonexistent/.cache/go-build目录下存储。

3. 解决

无法在launchpad指定GOCACHE环境变量, 目前只能在自研的go源码中,在编译前export 设置GOCACHE环境变量。 据了解launchpad可以对/tmp目录有管理权限。

GOCACHE.png

将修改后的go源码包,再次推送launchpad平台编译成功!