我的Glibc升级方案(无需重启,无需使用另一个系统的live cd)~~~

来源:互联网 发布:网络作家水平面 编辑:程序博客网 时间:2024/05/21 17:40

实验室的cluster是2003年安装的了~~~用的是redhat9 AS3, kernel2.4的。一直想尽量不要遇到非升级内核的情况,懒得去做一些麻烦的事情。如果不小心把整个cluster弄崩溃了,我也就崩溃了。。。

 

但是,前几天,实在没法子了~~~要在网格上运行matlab程序,好消息是现在matlab有java builder可以很容易的转换成java程序让你运行;坏消息是,当然没那么容易放过你咯,你得在未装有matlab的机器上装上人家的matlab common runtime(MCR)。哎,很合理很合理,那只有装呗!

 

可悲的是,这个玩意儿装好了,java程序还是不能运行。因为,调用到MCR里的动态链接库时,会报错,提示你机器上的libc.so.6没有GLIBC_2.3.4。。。 好啦,一阵狂百度狂google,发现没有办法,只能升级Glibc了。

 

好吧,结果发现咱们的kernel也得升级,不然装不上glibc。。。。okay,从头开始。

 

在网上找到一篇解决方案:《使用源代码将 Glibc 升级到2.6》http://hi.baidu.com/liyangzhao/blog/item/f5e541127ffec352f919b818.html(我找了半天,都不能确定这位朋友是不是原创作者,但是文章最后有写作者名和联系方式)

 

仔细看了看,应该是可行的。但是我还是首先用更安全更可行的方法升级了我的内核到2.6.18.(过程略)

 

之后,我按照这个文章的方法成功的在一台机器上进行了Glibc的升级,version2.3.2到version2.9!

 

然后郁闷的事就来了。按照它的说法:“为了安全升级Glibc,在升级前必须做好详细的部署和备份,即使是升级失败,系统也要能够还原为原来的状态。升级Glibc失败后,一般是无法重新启动系统的,必须使用另外一个可以启动计算机的Linux系统启动,挂载升级失败的根文件系统,恢复系统的Glibc为原来的状态。因此,准备另外一个可以启动 的Linux系统,是必需的。”

 

我又google了一下,似乎大家都是用这种类似的方法,用live cd来完成glibc的完整安装。

天,实验室摆的密密麻麻的40台PC,我不可能每台都搬下来插上光驱用live cd进行修复的吧。。。

其间我还去论坛上请教过,有人说用SystemImage来做,但那个是整个系统的克隆吧,我不想重装我那些机器上的东西了~考虑了一下,还是决定回到问题的根本,看下有没有不用live cd就可以办到的法子~~~

 

于是,偶仔细研读了glibc官网上的FAQ,终于让我找到了答案。

http://www.gnu.org/software/libc/FAQ.html#s-3.18大家看这里的3.18条:

 

3.18. After upgrading to glibc 2.1, I receive errors about unresolved symbols, like `_dl_initial_searchlist' and can not execute any binaries. What went wrong?

{AJ} This normally happens if your libc and ld (dynamic linker) are from different releases of glibc. For example, the dynamic linker /lib/ld-linux.so.2 comes from glibc 2.0.x, but the version of libc.so.6 is from glibc 2.1.

The path /lib/ld-linux.so.2 is hardcoded in every glibc2 binary but libc.so.6 is searched via /etc/ld.so.cache and in some special directories like /lib and /usr/lib. If you run configure with another prefix than /usr and put this prefix before /lib in /etc/ld.so.conf, your system will break.

So what can you do? Either of the following should work:

  • Run `configure' with the same prefix argument you've used for glibc 2.0.x so that the same paths are used.
  • Replace /lib/ld-linux.so.2 with a link to the dynamic linker from glibc 2.1.

     

You can even call the dynamic linker by hand if everything fails. You've got to set LD_LIBRARY_PATH so that the corresponding libc is found and also need to provide an absolute path to your binary:

LD_LIBRARY_PATH=<path-where-libc.so.6-lives> /<path-where-corresponding-dynamic-linker-lives>/ld-linux.so.2 /<path-to-binary>/binary

For example `LD_LIBRARY_PATH=/libold /libold/ld-linux.so.2 /bin/mv ...' might be useful in fixing a broken system (if /libold contains dynamic linker and corresponding libc).

With that command line no path is used. To further debug problems with the dynamic linker, use the LD_DEBUG environment variable, e.g. `LD_DEBUG=help echo' for the help text.

If you just want to test this release, don't put the lib directory in /etc/ld.so.conf. You can call programs directly with full paths (as above). When compiling new programs against glibc 2.1, you've got to specify the correct paths to the compiler (option -I with gcc) and linker (options --dynamic-linker, -L and --rpath).

 

所以~~~我放心大胆的采用了这个方法,直接远程ssh到我需要升级的机器上。针对那篇文章的步骤,到了:

 

4.1 第一次make install

安装失败后,输入任何命令都是无效的,系统 只会重复"relocation error: /lib/tls/libc.so.6: symbol _dl_out_of_memory, version GLIBC_PRIVATE not defined in file ld-linux.so.2 with link time reference"的错误信息,重新启动计算机在启动中就会失败,根本无法进入原Linux系统。

出现这样的 错误的原因是Coreutils的应用程序都依赖于/lib/tls/下的动态库,在make install的时候,/lib/ld-linux.so.2从原来指向ld-2.3.5.so被改为指向ld-2.6.so,但这个时候 /lib/tls/libc.so.6指向的仍然是/lib/tls/libc-2.3.5.so。/lib/ld-linux.so.2和 /lib/tls/libc.so.6各自指向不同版本的库文件导致了Coreutils的命令执行失败,从而make install也失败。

这 个时候,就要用另外一个Linux系统启动,挂载升级失败的根文件系统,把原根文件系统的/lib/tls/下的链接全部改为指向2.6版本的库文件,具 体就是/lib/tls/libc.so.6,/lib/tls/libm.so.6, /lib/tls/libpthread.so.0和/lib/tls/librt.so.1这4个软链接分别指向libc-2.6.so, libm-2.6.so,libpthread-2.6.so和librt-2.6.so。libthread_db.so.1仍然是指向 libthread_db-1.0.so,但这个时候/lib/libthread_db-1.0.so已经是Glibc2.6版本的了,原 /lib/tls/libthread_db-1.0.so必须被替换为Glibc2.6版本的libthread_db-1.0.so。

笔者使用Knoppix 5.0.1 Live CD启动计算机,启动后,打开一个控制台,执行"su"命令切换为root,执行以下命令:


# cd /mnt
# mkdir m1
# mount -t xfs /dev/hda5 /mnt/m1
# cd /mnt/m1/lib/tls
# cp -f ../libthread_db-1.0.so .
# cp ../libc-2.6.so .
# cp ../libm-2.6.so .
# cp ../libpthread-2.6.so .
# cp ../librt-2.6.so .
# ln -sf libc-2.6.so libc.so.6
# ln -sf libm-2.6.so libm.so.6
# ln -sf libpthread-2.6.so libpthread.so.0
# ln -sf librt-2.6.so librt.so.1

 

 

 

我于是就直接:(本人使用的是redhat,所以cd /lib/tls, 如果你使用的是其他系统,请仔细查看你tls的so动态链接库都在哪里哦。比如,偶本本ubuntu的就是在/lib/tls/i686/cmov下的)


# cd /lib/tls
# LD_LIBRARY_PATH=/lib.2.3.2 /lib.2.3.2/ld-linux.so.2 /bin/cp -f ../libthread_db-1.0.so .
# LD_LIBRARY_PATH=/lib.2.3.2 /lib.2.3.2/ld-linux.so.2 /bin/cp  ../libc-2.9.so .
# LD_LIBRARY_PATH=/lib.2.3.2 /lib.2.3.2/ld-linux.so.2 /bin/cp  ../libm-2.9.so .
# LD_LIBRARY_PATH=/lib.2.3.2 /lib.2.3.2/ld-linux.so.2 /bin/cp  ../libpthread-29.so .
# LD_LIBRARY_PATH=/lib.2.3.2 /lib.2.3.2/ld-linux.so.2 /bin/cp  ../librt-2.9.so .
# LD_LIBRARY_PATH=/lib.2.3.2 /lib.2.3.2/ld-linux.so.2 /bin/ln -sf libc-2.9.so libc.so.6
# LD_LIBRARY_PATH=/lib.2.3.2  /bin/ln -sf libm-2.9.so libm.so.6
# LD_LIBRARY_PATH=/lib.2.3.2  /bin/ln  -sf libpthread-2.9.so libpthread.so.0
# LD_LIBRARY_PATH=/lib.2.3.2  /bin/ln  -sf librt-2.9.so librt.so.1

 

/lib.2.3.2文件夹是之前对/lib文件夹的备份,详情请见那篇参考资料咯!;)

 

这个时候,你执行/lib/libc.so.6就可以看到版本已经变成你升级的那个版本号了哦,偶的是2.9 :)

 

 

小结:

1. 用此方法升级Glibc可以省去用live cd挂载系统这一步骤,无需重启,一步到位!

2. 需要注意的是,在升级中可能会遇到其他错误,比如gcc版本不够之类的,我使用的是gcc4.1.2

3. 本人用了linux没多久,也许你早就发现可以这么做了,呵呵。或者,也许会有其他更好的方法,欢迎大家和我交流哦!