问题
在日常的使用中,我们主要是使用git来进行代码的管理。虽然平时在开发时方便了,但是当bin文件分发到测试环境或者线上环境之后有了问题,我们回头再来找相应代码就显得无能为力了,最近两天在看Prometheus项目的启动信息时发现它会打出十分详细的编译信息,包括:
- 编译器版本
- branch
- git的md5
- 编译日期
- 编译用户&机器
如下:
1 | level=info ts=2018-02-12T08:46:09.8333802Z caller=main.go:215 msg="Starting Prometheus" version="(version=2.0.0, branch=HEAD, revision=0a74f98628a0463dddc90528220c94de5032d1a0)" |
我们可以看到,从输出中我们能非常准确的定位到该bin文件对应的git代码,是不是很方便?方向找到了,那么就开始想办法加到自己代码里面吧
调研
通过关键字定位到了代码文件,但是比较奇怪的是在代码中并没有对以上相关变量进行赋值的地方。想了一下就想明白了,像编译信息,应该是在编译时候进行初始化,之后再怎么运行都不会再对变量进行相关操作了,所以这些变量应该是在文件中进行了声明,但是在编译的时候进行了初始化的。经过了漫长的定位终于在阴差阳错的情况下看到了如下语句:
1 | build -o xxx -ldflags -X xxx.Version=0.15.0 -X xxx.Revision=9a5bd5f8e4b9c609c46af1496b415fc0667b9d83 -X xxx.Branch=master -X xxx.BuildUser=shadage@mt -X xxx.BuildDate=20180212-05:31:05 |
看到了吗,在build的阶段对包里面的几个变量进行了赋值,这里使用的是配套的打包工具比较复杂这里不做详细介绍了,到这里我们就知道应该怎么做了,就是在build的时候增加上-ldflags ‘’-X package.Variable=1234’这种方式进行变量的初始化就ok啦,这里需要注意下加上单引号,因为这个选项最终是要传递给连接器的
实现
方法已经很明确了,只需要在编译的时候进行以上信息的获取,并且在编译的时候把这些信息传递给编译器就ok了,一下给出一个简单的实现:
1 | 获取代码版本信息 |
1 | //go版本通过runtime模块获取 |
以上,就达到了获取bin文件对应代码信息的目的。
当然啦,以上只是一种方法,一种比较正统的方法,对于不知道编译器、连接器这种底层的同学其实也是可以实现的,例如,我在代码中使用关键字对以上变量进行标示,在大宝之前获取到了git等信息之后,我再使用sed修改一些代码文件也是ok的,只是比较野啦:)毕竟条条大路通罗马,方法不重要,目的达到才是最重要的。
转载请注明来源链接 http://just4fun.im/2018/02/01/golang增加预编译信息/ 尊重知识,谢谢:)