记一次文件无法执行的查错过程

遇到的问题

在运行docker下的ngrok后,生成的客户端。
windows下的版本可以正常运行。
linux下的版本在ubuntu16.04上运行则报错-bash: /home/xx/ngrok: No such file or directory

查找原因过程

x01

了解到file <filename>可以查看查看可执行文件的类型。
无法执行的文件是这样的文件类型。
ngrok: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, not stripped

x02

通过搜索,看到与这类似的问题
https://serverfault.com/questions/730922/how-can-i-get-information-about-a-binary-file-that-wont-execute

经过对比,发现下面回答中,/lib64/ld-linux-x86-64.so.2与无法执行文件的文件信息/lib/ld-musl-x86_64.so.1不一样

x03

通过查找以前可以运行的ngrok版本的文件信息。得到如下文件信息。
ngrok: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, not stripped
更加证实了上面的lib与lib64的差别问题。

猜想就是编译引用的库路径不对。

x04

客户端的编译是在hteen/ngrok这个镜像中完成的。
找到这个镜像的Dockerfile。
FROM golang:1.7.1-alpine直接用的golang的环境。
感觉是这个环境编出来的与ubuntu不兼容。
于是换成了FROM ubuntu16.04又做了一个镜像。
在以ubuntu16.04为基础镜像的环境下,重新生成了客户端是可以执行的。

在修改的过程中,要把apk add 要换成apt-get install

0x05

为了验证是不是与go的版本相关
后面我又以golang:1.9beta1-alpine做了一个镜像。
生成了客户端也是不能执行的

后面我又以golang:1.8.3做了一个镜像。
生成了客户端是能执行的

0x06

最后就回到了alpine是什么
Alpine Linux 是一个社区开发的面向安全应用的轻量级 Linux 发行版。Alpine采用了musl libc和busybox以减小系统的体积和运行时资源消耗。

Docker准备使用Alpine Linux替代之前的Ubuntu做为官方默认的宿主环境(基础镜像)
而Alpine Linux只有1层,5M。Ubuntu有4层,188M。

最后的结论

基础基础镜像是Alpine的golang环境,编译出来的64位客户端无法在ubuntu上执行。

参考资料

http://www.lampweb.org/linux/2/20.html
http://dockone.io/article/1014
https://hub.docker.com/_/golang/
https://serverfault.com/questions/730922/how-can-i-get-information-about-a-binary-file-that-wont-execute