在低版本glibc的环境里运行基于高版本glibc编译的可执行程序

简介: 在低版本glibc的环境里运行基于高版本glibc编译的可执行程序

背景

在工作过程中,我们经常会遇到可执行程序依赖的glibc跟当前运行环境的版本不兼容,导致应用程序无法运行,比如:

/lib64/libc.so.6: version `GLIBC_2.14’ not found

原因是运行环境的glibc的版本比编译环境的glibc的版本低。

几种可行的方法

1. 升级当前运行环境的glibc

2. 静态编译

将依赖高版本glibc的可执行程序进行静态编译

3. 修改引用了高版本的glibc的elf文件

4. 使用高版本glibc的容器

使用一个运行有高版本glibc的容器,将可执行程序运行在容器里

5. 通过环境变量控制可执行程序对动态库的加载

将可执行程序依赖的动态库提取出来,然后通过LD_LIBRARAY_PATH指定动态库的加载路径,然后用其中的动态链接器来执行可制成程序,下面以qemu为例,具体步骤如下.

在编译环境下找到qemu依赖的动态库

$ ldd qemu-system-x86_64
        linux-vdso.so.1 (0x00007ffc26162000)
        libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007fc520b46000)
        libdw.so.1 => /lib/x86_64-linux-gnu/libdw.so.1 (0x00007fc520ae7000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc520acb000)
        libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007fc520a9e000)
        libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007fc5208bd000)
        libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007fc52085d000)
        libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007fc520731000)
        libbpf.so.0 => /lib/x86_64-linux-gnu/libbpf.so.0 (0x00007fc5206e3000)
        libncursesw.so.6 => /lib/x86_64-linux-gnu/libncursesw.so.6 (0x00007fc5206a9000)
        libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fc520679000)
        libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007fc520673000)
        libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007fc520660000)
        libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fc520659000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc52050a000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc5204ef000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc5204cc000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc5202da000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc521d5a000)
        libelf.so.1 => /lib/x86_64-linux-gnu/libelf.so.1 (0x00007fc5202be000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc5202b6000)
        liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007fc52028d000)
        libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007fc52022d000)
        libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fc520202000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fc5201e6000)
        libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007fc5201da000)
        libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fc520165000)
        libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007fc52010e000)
        libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fc52007d000)

将qemu依赖的动态库全部拷贝到一个目录下

  • 将上面的输出放到一个文件里,如下:
$ cat deps.txt
libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f719a1ce000)
libdw.so.1 => /lib/x86_64-linux-gnu/libdw.so.1 (0x00007f719a16f000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f719a153000)
libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f719a126000)
libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f7199f45000)
libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f7199ee5000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f7199db9000)
libbpf.so.0 => /lib/x86_64-linux-gnu/libbpf.so.0 (0x00007f7199d6b000)
libncursesw.so.6 => /lib/x86_64-linux-gnu/libncursesw.so.6 (0x00007f7199d31000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f7199d01000)
libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f7199cfb000)
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f7199ce8000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f7199ce1000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7199b92000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7199b77000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7199b54000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7199962000)
libelf.so.1 => /lib/x86_64-linux-gnu/libelf.so.1 (0x00007f7199946000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f719993e000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f7199915000)
libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007f71998b5000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f719988a000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f719986e000)
libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f7199862000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f71997ed000)
libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007f7199796000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f7199705000)
  • 编写一个脚本,将动态库拷贝到指定目录下:
#!/bin/bash
rm -rf libs
mkdir libs
while read line
do
        lib_path=`echo $line | awk '{print($3)}'`
if [ -z "$lib_path" ];then
continue
fi
cp $lib_path ./libs
done < deps.txt
chmod +x libs/*
  • 把动态链接器也拷贝到libs下
$ cd libs/
$ cp /lib64/ld-linux-x86-64.so.2 .

测试

  • 使用下面的命令来运行
**#!/bin/bash
kvm_path=`realpath $0`
kvm_path=`dirname $kvm_path`
abslibdir=$kvm_path/libs
loader=$abslibdir/ld-linux-x86-64.so.2
binary=$kvm_path/qemu-system-x86_64
LD_LIBRARY_PATH="$abslibdir/" "$loader" "$binary" "$@"
# exec "$loader" --library-path "$abslibdir" "$binary" "$@"
BASH 复制 全屏
  • 测试
$ ./run.sh --version
QEMU emulator version 8.0.0
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers

完。

相关文章
VS Code Server 离线安装(解决超时,XHR Failed等问题)
VS Code Server 离线安装(解决超时,XHR Failed等问题)
|
Linux C语言 Python
CentOS7下升级GLIBC2.31
CentOS7下升级GLIBC2.31
4919 0
CentOS7下升级GLIBC2.31
已解决 BrokenPipeError: [Errno 32] Broken pipe
已解决 BrokenPipeError: [Errno 32] Broken pipe
10206 156
已解决 BrokenPipeError: [Errno 32] Broken pipe
|
Linux C语言
Linux These critical programs are missing or too old: compiler
Linux These critical programs are missing or too old: compiler
3664 0
Linux These critical programs are missing or too old: compiler
|
9月前
|
安全 C语言 Docker
从零开始学构建Docker镜像:4种实用方法+生产级实践规范
本文系统讲解Docker镜像构建四大方法,聚焦生产实践,涵盖环境搭建、Dockerfile规范、多阶段构建、安全管控与CI/CD集成,强调非root运行、镜像瘦身及可追溯Tag规范,助力开发者掌握从开发到生产的全链路容器化技能。
1986 5
|
缓存 运维 NoSQL
Redis 集群化部署实战:打造高可用、可扩展的缓存系统
本文详细介绍Redis集群化部署方案,涵盖架构设计、环境准备、配置优化、Docker部署、集群管理、监控运维及故障处理,助你构建高可用、可扩展的分布式缓存系统。
1148 2
|
存储 Linux C语言
Linux|如何安装和运行多个 glibc 库
Linux|如何安装和运行多个 glibc 库
5859 5
|
Web App开发 缓存 UED
如何设置浏览器的缓存策略?
【10月更文挑战第23天】通过合理地设置浏览器的缓存策略,可以在提高网页性能、减少网络流量的同时,确保用户能够获取到最新的内容,从而提升用户体验和网站的性能优化效果。
1780 60
|
中间件 Linux vr&ar
Centos7升级Glibc
centos7升级glic问题
4318 0
|
Linux API 图形学
OpenGL生态中的GL, GLU, GLUT, GLX, GLEW, GLEE和GLEXT详解
该文介绍了OpenGL生态系统中的关键组件,包括GL(基础绘图API)、GLU(提供辅助函数)、GLUT(窗口管理和事件处理)、GLX(X Window系统上的OpenGL扩展)、GLEW和GLEE(动态查询和封装OpenGL扩展)以及GLEXT(OpenGL扩展集合)。这些库和工具协同工作,帮助开发者构建跨平台的图形应用程序,提升兼容性与功能。理解它们的作用对优化OpenGL编程至关重要。