渡劫再次踩坑集锦,还是记录下,也分享给各位受困扰的小伙伴们。

简单说: 在alpine镜像内,运行在centos下编译的go二进制文件出现/bin/sh xxx not found

环境:

镜像:alpine3.9

运行命名: 自己编译的promethus exporter

直接上解决过程,和说明吧,如图:


这种情况是因为动态链接库位置错误导致的,alpine镜像使用的是musl libc而不是gun libc。因而动态链接库的位置不一致。

而一般二进制文件在linux系统下编译,动态链接库是到/lib64目录下的,在alpine镜像内无/lib64目录(参见)。

可通过ldd查看二进制文件的链接库验证。解决版本是将动态库链接到需要的位置。

在基础镜像内执行:mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2


另外引发另一个规范的问题,其实这个问题已经踩过一次了,并且放在基础的Dockerfile内,因为是监控镜像就未按照线上流程,直接在alpine镜像打包。如果使用之前的基础镜像可避免类似的问题。

强烈建议:使用alpine镜像做基础镜像的项目,在直接使用alpine镜像之前,进行一次初始化,然后用作通用的基础镜像,如下是之前的基础镜像,其实已经考虑了动态库的问题。 所以是再次做了无用功,浪费了一个下午和一个晚上。。。。

参考文档

https://stackoverflow.com/questions/34729748/installed-go-binary-not-found-in-path-on-alpine-linux-docker

https://github.com/docker-library/openjdk/issues/77

https://github.com/gliderlabs/docker-alpine/issues/11


https://github.com/sgerrand/alpine-pkg-glibc/releases



分割线

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

参考:https://www.cnblogs.com/tongongV/p/10744050.html

d-linux.so.2 是linux下的动态库加载器/链接器,这篇文章主要来讲一下 ld-linux.so.2 是如何和Linux 以及相关应用打交道的。

1. 什么是 ld.linux.so ? 

很多现代应用都是通过动态编译链接的,当一个 需要动态链接 的应用被操作系统加载时,系统必须要 定位 然后 加载它所需要的所有动态库文件。 在Linux环境下,这项工作是由ld-linux.so.2来负责完成的,我们可以通过 ldd 命令来查看一个 应用需要哪些依赖的动态库:

$ ldd `which ls`      linux-gate.so.1 =>  (0xb7fff000)      librt.so.1 => /lib/librt.so.1 (0x00b98000)      libacl.so.1 => /lib/libacl.so.1 (0x00769000)      libselinux.so.1 => /lib/libselinux.so.1 (0x00642000)      libc.so.6 => /lib/libc.so.6 (0x007b2000)      libpthread.so.0 => /lib/libpthread.so.0 (0x00920000)      /lib/ld-linux.so.2 (0x00795000)      libattr.so.1 => /lib/libattr.so.1 (0x00762000)      libdl.so.2 => /lib/libdl.so.2 (0x0091a000)      libsepol.so.1 => /lib/libsepol.so.1 (0x0065b000)

当最常见的ls小程序加载时,操作系统会将 控制权 交给 ld-linux.so 而不是 交给程序正常的进入地址。 ld-linux.so.2 会寻找然后加载所有需要的库文件,然后再将控制权交给应用的起始入口。

上面的ls在启动时,就需要ld-linux.so加载器将所有的动态库加载后然后再将控制权移交给ls程序的入口。

ld-linux.so.2 man page给我们更高一层的全局介绍, 它是在 链接器(通常是ld)在运行状态下的部件,用来定位和加载动态库到应用的运行地址(或者是运行内存)当中去。通常,动态链接是 在连接阶段当中 隐式指定的。 gcc -W1 options -L/path/included -lxxx 会将 options 传递到ld 然后指定相应的动态库加载。 ELF 文件提供了相应的加载信息, GCC包含了一个特殊的 ELF 头: INTERP, 这个 INTERP指定了 加载器的路径,我们可以用readelf 来查看相应的程序

$ readelf -l a.outElf file type is EXEC (Executable file)Entry point 0x8048310There are 9 program headers, starting at offset 52Program Headers:  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align  PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4  INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1      [Requesting program interpreter: /lib/ld-linux.so.2]  LOAD           0x000000 0x08048000 0x08048000 0x004cc 0x004cc R E 0x1000  LOAD           0x000f0c 0x08049f0c 0x08049f0c 0x0010c 0x00110 RW  0x1000. . .

 

ELF 规格要求,假如 PT_INTERP 存在的话,操作系统必须创建这个 interpreter文件的运行映射,而不是这个程序本身, 控制权会交给这个interpreter,用来定位和加载所有的动态库,

©著作权归作者所有:来自51CTO博客作者憬薇的原创作品,如需转载,请注明出处,否则将追究法律责任

好知识,才能预见未来

赞赏

0人进行了赞赏支持

更多相关文章

  1. 简单实现选项卡、懒加载、轮播图案例
  2. Composer常用指令以及自动加载器的使用方式
  3. JavaScript初学习/之classList:动态设置元素类、dataset: 读写自
  4. Mybatis系列全解(八):Mybatis的9大动态SQL标签你知道几个?提前致女神
  5. Spring Cloud Gateway 扩展支持动态限流
  6. Ajax数据异步加载、无刷新分页、编辑与删除功能
  7. 入域时候提示无法加载指定的脱机注册表配置单元处理
  8. 第11章 0223-命名空间2与数据库基础1,学习心得、笔记(命名空间引
  9. PHP命名空间类三种引用|类导入命名冲突解决|自动加载类|mysql操

随机推荐

  1. android view holder 优化
  2. 一对一直播系统开发Android ProgressBar
  3. Android中软键盘使用总结(一)
  4. android 里使用Socket进行发送消息案例
  5. cocos2dx 移植android 报错
  6. 学习android!!!! 谁是android的机器啊?
  7. Android文字的复制和粘贴
  8. Android使用AttributeSet自定义控件的方
  9. 安卓高手之路之PackageManagerservice
  10. FregServer进程,返回BR_REPLY