这边以前的大多数项目都用的java,而本身用的c++,等到快要上线的时候才发现线上机器的gcc和libc的版本都巨低,跟本身测试开发用的环境不兼容,编译出的c++可执行文件无法运行。解决c++程序的移植问题费了挺大周章,以下是一个具体记录:java
一、问题描述linux
如上所述,线上机器与开发机环境不兼容,须要作c++程序的移植。c++
二、表现redis
细节不表,总之就是程序无法运行,找不到对应的库。以下给出几个跟gcc有关的错误提示:测试
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not foundspa
/lib64/libc.so.6: version `GLIBC_2.7' not foundblog
等等开发
三、尝试过的方法io
在开发机上使用静态编译能够解决大部分问题,例如thrift、cgi、redis等相关库采用静态编译,线上机器就不用装对应软件就能够运行程序。这样,正常的想法是把gcc相关的库也静态编译进可执行文件,那么线上机器就能够直接运行了吧,想法是好的,惋惜咱们尝试了很长时间,仍是以失败了结,线上环境仍是不能运行。编译
四、必定不要作
惨痛教训,必定不要随便动线上机器的libc等环境,尤为不要动内核/lib64/libc.so.6的符号连接(我当时头脑发热,将一些报错的库文件从开发机拷贝到线上机器,而后更改线上机器库文件的符号连接,结果出了很大问题),或者草率升级线上机器的libc(也是教训),这样会形成系统直接down掉,由于内核跟用户态的交互不少都依赖于libc库,升级后与内核不兼容,则会形成基本的ls、sudo等都无法执行。没法进入sudo权限,就没法恢复/lib64下被更改或升级的库文件,只能重启进入急救模式,这对运行有线上服务的机器是很致命的。若是更改了libc.so.6等的软链接或盲目升级libc等,执行基本命令时会报相似以下错误:
error while loading shared libraries: /lib64/libc.so.6: ELF file OS ABI invalid
这是虽然能够经过LD_PRELOAD=/lib64/libc-2.5.so ls 加载旧的libc库,执行一些简单命令,可是sudo倒是怎么都进不去的。因此必定提醒你们不要在线上机器上作这种事。
五、最终的解决办法
1)线上机器配置:
能够在用户目录下,创建一个文件夹$dir/Mylib64,为了下面表述方便,$dir表示该文件夹的绝对路径。文件夹下存放开发机中/lib64/文件夹下gcc对应的库文件,例如以下几个:
2)开发机编译选项:
在开发机makefile的g++编译选项最后,添加以下选项用来指定动态库的优先搜索路径和动态连接器:
-Wl,--rpath=$dir/Mylib64 -Wl,--dynamic-linker=$dir/Mylib64/ld-linux-x86-64.so.2
其中$dir就是1)中的绝对路径。
这样开发机make出的可执行文件就能够在线上机器上运行了。