redis-server进程启动报错version `GLIBC_2.14' not found 的根因及解决方案

1.问题基本信息

问题级别

时间

问题简述

   严重

2017-11-23

安装环境与编译环境GLIBC版本差异;Redis启动报错,编译问题,操作系统库函数依赖

 2. 问题场景

安装AC大包过程中报错:Start module: redis process FAILED. 定位发现Redis-server进程没有拉起,尝试手动拉起Redis-server进程失败,报错:/lib64/libc.so.6: version `GLIBC_2.14' not found(required by /opt/…/redis-server)。

3. 表因分析

很明显,报错显示当前Linux系统找不到GLIBC_2.14版本库,而Redsi-server依赖GLIBC_2.14,使用命令:strings /lib64/libc.so.6 | grep GLIBC查看当前系统GLIBC版本:可以看出,当前系统最高支持GLIBC_2.11,低于需要的2.14。至此,可定性为:编译redis-server的编译机GLIBC版本(2.14)高于目标安装机的GLIBC版本(2.11),即:高版本编译,低版本安装,因此安装失败。但根因并不在此!

controller-192-168-1-3:/opt/controller/redis/bin # strings /lib64/libc.so.6 | grep GLIBC

GLIBC_2.2.5

GLIBC_2.2.6

GLIBC_2.3

GLIBC_2.3.2

GLIBC_2.3.3

GLIBC_2.3.4

GLIBC_2.4

GLIBC_2.5

GLIBC_2.6

GLIBC_2.7

GLIBC_2.8

GLIBC_2.9

GLIBC_2.10

GLIBC_2.11

GLIBC_PRIVATE   


使用命令:strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC (编译机是Ubuntu)查看编译机的GLIBC版本:编译机GLIBC版本高达2.18(为谨慎起见,查看libc.so.6的软连接,确认实际采用的GLIBC版本)。如果是GLIBC版本问题,编译机的版本远高于目标安装机,上述问题不应该为“偶现”,应该“必现”,因此,GLIBC版本不是导致上述问题的根因。

controller-192-168-1-3:/opt/controller/redis/bin # strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC

GLIBC_2.2.5

GLIBC_2.2.6

GLIBC_2.3

GLIBC_2.3.2

GLIBC_2.3.3

GLIBC_2.3.4

GLIBC_2.4

GLIBC_2.5

GLIBC_2.6

GLIBC_2.7

GLIBC_2.8

GLIBC_2.9

GLIBC_2.10

GLIBC_2.11

GLIBC_2.12

GLIBC_2.13

GLIBC_2.14

GLIBC_2.15

GLIBC_2.16

GLIBC_2.17

GLIBC_2.18

GLIBC_PRIVATE

4. 根因分析

在redis-server所在路径下输入命令:objdump -T redis-server| fgrep GLIBC_2.14 查看redis-server依赖的GLIBC_2.14版本库的具体函数:截图可见,只有一个函数memcpy,依赖版本为GLIBC_2.14。

controller-192-168-1-3:/opt/controller/redis/bin # objdump -T redis-server| fgrep GLIBC_2.14

0000000000000000      DF *UND*  0000000000000000  GLIBC_2.14 memcpy


输入命令:objdump -T /lib64/libc.so.6 | fgrep memcpy,查看目标安装机支持的memcpy版本:截图可见,目标安装机仅支持GLIBC_2.2.5。

controller-192-168-1-3:/opt/controller/redis/bin # objdump -T /lib64/libc.so.6 | fgrep memcpy

000000000008c400  w   DF .text  0000000000000009  GLIBC_2.2.5 wmemcpy

00000000000eef00 g    DF .text  000000000000001b  GLIBC_2.4   __wmemcpy_chk

0000000000084670 g    DF .text  0000000000000465  GLIBC_2.2.5 memcpy

0000000000084660 g    DF .text  0000000000000009  GLIBC_2.3.4 __memcpy_chk


输入命令:objdump -T /lib/x86_64-linux-gnu/libc.so.6 | fgrep memcpy 查看编译机(docker编译)支持的memcpy版本:可见,编译机支持两种版本(2.14和2.2.5)。至此,根因找到:redis源码依赖memcpy函数,编译机概率性的采用memcpy[GLIBC_2.2.5]和memcpy[GLIBC2.14]编译redis-server,而目标安装机仅支持memcpy[GLIBC_2.2.5],由此导致redis-server概率性安装失败。

controller-192-168-1-3:/opt/controller/redis/bin # objdump -T /lib/x86_64-linux-gnu/libc.so.6 | fgrep memcpy

00000000000alcc0  w   DF .text  0000000000000009  GLIBC_2.2.5 wmemcpy

000000000010bdf0 g    DF .text  000000000000001b  GLIBC_2.4   __wmemcpy_chk

0000000000091620 g    DF .text  0000000000000465  GLIBC_2.14 memcpy

000000000008c420 g    DF .text  0000000000000465  (GLIBC_2.2.5) memcpy

0000000000108990 g    DF .text  0000000000000009  GLIBC_2.3.4 __memcpy_chk

5. 解决方案

可在redis源码中添加约束,显式指定所依赖的memcpy函数的GLIBC版本,需添加的约束代码如下:

__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");

【注意】只需在调用函数memcpy的源文件中加入此约束

解决方案验证例子

【步骤1】编写一个简单的C测试程序:test.c,功能:将s中的字符串复制到字符数组d中

#include<stdio.h>
#include<string.h>
int main()
{
        char*s="Golden Global View";
        char d[20];
        memcpy(d,s,strlen(s));
        d[strlen(s)]='\0';
        printf("%s",d);
        getchar();
        return 1;
}

【步骤2】在test.c同级目录下执行编译命令:gcc -o test test.c

【步骤3】运行test可执行文件:正常

【步骤4】查看test依赖的memcpy函数的GLIBC版本:可以看出,memcpy采用的是GLIBC_2.14

将编译的好的可执行文件test复制到目标机执行,报错:version `GLIBC_2.14′ not found ,查看test依赖GLIBC_2.14的函数名称,为memcpy,查看目标机支持的memcpy函数版本:GLIBC_2.2.5

【步骤5】在源码中对依赖的memcpy函数进行版本约束,使其按指定版本编译。添加约束代码:__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");

#include<stdio.h>
#include<string.h>
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
int main()
{
        char*s="Golden Global View";
        char d[20];
        //clrscr();
        memcpy(d,s,strlen(s));
        d[strlen(s)]='\0';
        printf("%s",d);
        getchar();
        return 1;
}

【步骤6】执行编译,运行,检测memcpy的版本,可以看到,test依赖的memcpy的版本为GLIBC_2.2.5,约束是有效的。

【特别说明】如有任何疑问,请扫描二维码提问(GitChat):



猜你喜欢

转载自blog.csdn.net/jin_kwok/article/details/80319441