跳转至

glibc

glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。

Linux系统上基本所有程序运行都依赖glibc库,不同Linux发行版或同一发行版的不同版本glibc库的版本都可能不大一样,一般原则是Linux发行版更新越快,其glibc的版本越新,如Ubuntu大版本更新很快,其glibc库的版本比较新;同一Linux发行版,系统版本越新,glibc的版本也越新,如CentOS6.x的glibc版本为2.12,CentOS7.x的glibc版本为2.17,CentOS8.x为2.28。

在低版本glibc的Linux系统上编译的软件,可以在高版本glibc的Linux系统上运行,反之则报错,如在CentOS7.x上编译的软件无法在CentOS6.x上运行。

许多软件的作者经常会在glibc版本非常高的Linux系统上编译软件然后在github上发布,用户下载之后由于系统的glibc版本较低而无法运行,报类似如下的报错:

$ SVvadalidation -h
[47944] Error loading Python lib '/tmp/_MEIYlB3Lh/libpython3.8.so.1.0': dlopen: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /tmp/_MEIYlB3Lh/libpython3.8.so.1.0)
查看系统glibc版本
$ ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

集群目前的系统版本为CentOS7.x,glibc版本为2.17,10年前的版本,非常古老了,未来会有越来越多的软件出现glibc版本不够的报错。

解决办法有以下几种:

更换系统

出现glibc相关的报错,使用高版本glibc的系统即可解决。

常见服务器Linux系统版本对应的glibc版本如下,更多的Linux系统版本及对应的glibc库见 distrowatch

  • 系统版本:6.x,glibc版本:2.12,生命周期(EOL):2020-11
  • 系统版本:7.x,glibc版本:2.17,EOL:2024-06
  • 系统版本:8.5,glibc版本:2.28,EOL:2021-12
  • 系统版本:9,glibc版本:2.34,EOL:2021-12
  • 系统版本:Rocky 8.7,glibc版本:2.28,EOL:2029-05
  • 系统版本:Rocky 9.1,glibc版本:2.34,EOL:2032-05
  • 系统版本:12.04 LTS precise,glibc版本:2.15,EOL:2017-04
  • 系统版本:14.04 LTS trusty,glibc版本:2.19,EOL:2019-04
  • 系统版本:16.04 LTS xenial,glibc版本:2.23,EOL:2021-04
  • 系统版本:18.04 LTS bionic,glibc版本:2.27,EOL:2023-04
  • 系统版本:20.04 LTS focal,glibc版本:2.31,EOL:2025-04
  • 系统版本:22.04 LTS jammy,glibc版本:2.35,EOL:2027-04
  • 系统版本:24.04 LTS noble,glibc版本:2.39,EOL:2029-04
  • 系统版本:6.0 squeeze,glibc版本:2.11.2,EOL:2016-02
  • 系统版本:7.0 wheezy,glibc版本:2.13,EOL:2018-05
  • 系统版本:8.0 jessie,glibc版本:2.19,EOL:2020-07
  • 系统版本:9 stretch,glibc版本:2.24
  • 系统版本:10 buster,glibc版本:2.28
  • 系统版本:11 bullseye,glibc版本:2.31
  • 系统版本:12 bookworm,glibc版本:2.36

源码编译

软件作者分发的编译好的软件,依赖作者的编译环境和底层glibc库,运行时在低版本glibc的系统上出现找不到glibc库的兼容性报错。如果软件作者提供了软件的源代码,则下载源代码自行编译,编译之后的软件只会依赖当前系统的glibc库,不会出现glibc版本兼容性的问题。

安装高版本glibc

Danger

glibc是系统上非常底层的库,如果不是非常熟悉,切勿按照网上的教程用root账户一把梭安装高版本glibc、替换系统的库文件,其结果很可能是系统崩溃无法开机。

一般建议使用普通账户安装。

$ wget https://ftp.gnu.org/gnu/glibc/glibc-2.21.tar.gz
$ tar xf glibc-2.21.tar.gz && cd glibc-2.21
$ mkdir build && cd build
$ ../configure  -prefix=/path/to/install
$ make -j12 && make install
# 设置环境变量
$ echo $LD_LIBRARY_PATH=/path/to/install/lib >> ~/.bashrc
根据系统环境的情况,可能涉及到需要高版本gcc。

这种方式无法安装版本比较高的glibc,如在集群上,最高只能安装glibc 2.23,且能正常使用。再高一点的版本要么安装报错,要么使用的时候报错。

此外对于需要使用高版本glibc的.so动态链接库,此方法无效。

用户在集群上可以直接调用:module load glibc/2.23

patchelf

直接载入高版本的glibc后,部分软件运行出现类似如下的报错

Segmentation fault

libc.so.6: symbol _dl_find_dso_for_object, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 with link time reference

此种情况可以使用 patchelf 解决,其原理是可以改变二进制文件使用的 ld-linux.so.2,默认使用 /lib64/ld-linux-x86-64.so.2

Warning

patchelf 会改变二进制文件包的内容,其过程是不可逆的。因此为防止出现意外情况,使用 patchelf 之前建议先备份一下二进制文件。

软件运行过程中会用到安装的 glibc 库,因此建议将 glibc 安装在一个固定的位置,以免 glibc 改变了目录或被删除后,相关软件无法运行。

https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229

# glibc 版本报错
$ ./glnexus_cli
./glnexus_cli: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by ./glnexus_cli)

# patchelf 处理
$ module load patchelf/0.9
$ patchelf --set-interpreter  /public/home/software/opt/bio/software/Glibc/2.18/lib/ld-linux-x86-64.so.2  --set-rpath /public/home/software/opt/bio/software/Glibc/2.18/ glnexus_cli

# 正常运行
$ ./glnexus_cli-bak
[43076] [2024-10-06 23:31:46.729] [GLnexus] [info] glnexus_cli release v1.4.1-0-g68e25e5 Aug 13 2021
[43076] [2024-10-06 23:31:46.730] [GLnexus] [warning] jemalloc absent, which will impede performance with high thread counts. See https://github.com/dnanexus-rnd/GLnexus/wiki/Performance
Usage: ./glnexus_cli-bak [options] /vcf/file/1 .. /vcf/file/N
Merge and joint-call input gVCF files, emitting multi-sample BCF on standard output.

利用 patchelf 的 --set-rpath 选项,也可以永久更改二进制包使用的 GCC 版本,而不用每次写 LD_LIBRARY_PATH 环境变量

$ patchelf --set-interpreter  /public/home/software/opt/bio/software/Glibc/2.18/lib/ld-linux-x86-64.so.2  --set-rpath /public/home/software/opt/bio/software/Glibc/2.18/:/public/home/software/opt/bio/software/GCCcore/5.4.0/lib64/ myapp

glibc-all-in-one

glibc 安装比较费时间,其高版本的glibc不容安装成功,可以利用 glibc-all-in-one 这个项目下载使用编译好的 glibc。

$ git clone https://github.com/matrix1001/glibc-all-in-one
cd glibc-all-in-one

# 将可下载使用的glibc版本更新到list文件中
$ ./update_list
$ cat list
2.23-0ubuntu11.3_amd64
2.23-0ubuntu11.3_i386
2.23-0ubuntu3_amd64
2.23-0ubuntu3_i386
2.27-3ubuntu1.5_amd64
2.27-3ubuntu1.5_i386
2.27-3ubuntu1.6_amd64
2.27-3ubuntu1.6_i386
2.27-3ubuntu1_amd64
2.27-3ubuntu1_i386
2.31-0ubuntu9.16_amd64
2.31-0ubuntu9.16_i386
2.31-0ubuntu9_amd64
2.31-0ubuntu9_i386
2.35-0ubuntu3.8_amd64
2.35-0ubuntu3.8_i386
2.35-0ubuntu3_amd64
2.35-0ubuntu3_i386
2.37-0ubuntu2.2_amd64
2.37-0ubuntu2.2_i386
2.37-0ubuntu2_amd64
2.37-0ubuntu2_i386
2.38-1ubuntu6.3_amd64
2.38-1ubuntu6.3_i386
2.38-1ubuntu6_amd64
2.38-1ubuntu6_i386
2.39-0ubuntu8.3_amd64
2.39-0ubuntu8.3_i386
2.39-0ubuntu8_amd64
2.39-0ubuntu8_i386
2.40-1ubuntu3_amd64
2.40-1ubuntu3_i386

# 下载指定版本的glibc
$ ./download 2.27-3ubuntu1_amd64

# 查看下载的glibc
$ ls libs
2.27-3ubuntu1_amd64/

#patchelf 处理
patchelf --set-interpreter ./libs/2.27-3ubuntu1_amd64/ld-linux-x86-64.so.2 --set-rpath ./libs/2.27-3ubuntu1_amd64 --force-rpath myapp

使用singularity容器安装

创建glibc版本较高的singularity镜像,如 debian 11,将软件拷贝至debian 11的目录下,如/opt/,测试软件是否正常,如果正常则将该镜像打包使用。这一步需要有root权限才可以操作,一般建议在虚拟机上进行,如果出现问题,影响也不会太大。这里以SVvadalidation为例进行操作说明。

$ pwd
$ /root
$ unzip SVvaliation-main.zip
$ singularity  build --sandbox  ./debian  docker://debian:11

# 进入debian镜像的shell,将软件拷贝至/opt/目录下
$ singularity  shell --writable ./debian
> cp -r /root/SVvaliation-main /opt/

# 测试是否可用
$ singularity  exec ./debian /opt/SVvaliation-main/dist/SVvadalidation -h

# 打包镜像
$ singularity build debian_11.sif ./debian

# 将打包好的镜像传到集群上使用
此种方式基本可以满足所有glibc版本不够高的需求。可能部分软件运行时还需要一些其它的库,均需要在镜像中装好。此方式缺点也比较明显,每个软件都需要单独打包镜像,比较繁琐。

使用singularity容器调用

此方式跟上一种方式的区别在于,无需root权限,普通用户就可以操作,不需要将软件拷贝至镜像中,pull一次镜像之后其它的软件都可以使用,比较方便。 核心点在于调用时,使用singularity绑定目录的特性将软件目录绑定到镜像中,使软件在镜像的环境中运行。

# pull镜像
$ singularity pull docker://debian:11
使用
$ singularity exec -B ./SVvaliation-main/:/opt/ $IMAGE/debian/debian11.sif /opt/dist/SVvadalidation -h

Info

集群镜像目录中有debian 11的镜像,可以直接使用$IMAGE/debian/debian11.sif,glibc版本为2.31。

注意事项

如果程序运行需要的数据不在当前目录挂载的存储上,则需要将该目录绑定到镜像中。

$ singularity exec -B ./SVvaliation-main/:/opt/  debian11.sif /opt/dist/SVvadalidation test.bed /data/test/test.cram
[E::hts_open_format] Failed to open file "/data/test/test.cram" : No such file or directory
Traceback (most recent call last):
    File "SVvadalidation.py", line 26, in <module>
    File "pysam/libcalignmentfile.pyx", line 751, in pysam.libcalignmentfile.AlignmentFile.__cinit__
    File "pysam/libcalignmentfile.pyx", line 950, in pysam.libcalignmentfile.AlignmentFile._open
FileNotFoundError: [Errno 2] could not open alignment file `Sha_15_sorted.cram`: No such file or directory
[29216] Failed to execute script 'SVvadalidation' due to unhandled exception!

# 将/data/test/目录绑定到容器中的/mnt/目录后正常运行
$ singularity exec -B ./SVvaliation-main/:/opt/ -B /data/test/:/mnt/ debian11.sif /opt/dist/SVvadalidation test.bed test.cram 
本文阅读量  次
本站总访问量  次