检测进程是否为Go进程

不说前提了,就是想明确知道一个进程是什么语言写的,像Python,Java都可以一眼看出来,但是Go这种编译型语言如何检测呢?

直觉是解析Go编译后文件格式。

最初看到这篇文章:

https://blog.wolfogre.com/posts/mechanism-of-gops/

使用gdb检测:

但是如果线上环境没有gdb命令呢?有没有其他方法

google有gops工具,可以直接查看。

https://github.com/google/gops/blob/master/goprocess/gp.go

一般问题可能就到此为止了,但是我还想继续深入调查,毕竟线上环境一般也没有这个命令,使用这个工具还得手动上传,不符合实际情况。

我们继续查看gops如何实现的

https://github.com/google/gops/blob/master/goprocess/gp.go#L123

https://github.com/google/gops/blob/master/goprocess/gp.go#L123

可以看到使用gops使用 goversion 模块

goversion 模块怎样实现的呢?

https://github.com/rsc/goversion/blob/master/version/read.go#L37

使用 openExe() 函数读取文件并解析的

openExe() 怎样实现的呢?

https://github.com/rsc/goversion/blob/597212e462da05a7902d6cea0ec895a0d9b8b218/version/exe.go#L36

读取文件字节码并解析,分情况:ELF文件格式(Linux),MZ文件格式(windows)

也即:(以Linux举例)

读取文件为ELF格式,遍历,如果出现 .note.go.buildid 则表示该文件为Go编译文件

既然是解析ELF文件,可以直接用readelf命令来解析呀

可以看到红框内的 .note.go.buildid 

证明了该文件是go编译后的文件。

其实不止 .note.go.buildid,截图中的其他项也表明了文件的Go身份,比如 .go.buildinfo 

所以,我们可以通过readelf命令检测进程是否为Go进程。而几乎所有线上环境都有此命令

实际上辨别的方式不止这一种,例如 https://github.com/rsc/goversion/blob/master/version/read.go#L37 给出的多种判定方式:

Plus:

ELF文件格式

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注