glibc升级血泪史

在没有工作任务的时候,总要学点东西

一个临时的目标是hadoop

了解了hadoop的大致功能作用后,开始着手实战hadoop

使用阿里云的ecs,最初打算自己编译源码安装hadoop,且是最新稳定版本2.5.1,但过程是艰难的。

按照http://pravinchavan.wordpress.com/2013/04/14/building-apache-hadoop-from-source/,一些准备工作没问题,但用maven真正编译时,开始是ProtocolBuffer的版本不对,换了最新的,然后又是太新了..必须指定版本..折腾再折腾..终于..我放弃了..原因有二:1.我的技术方向不是java,对maven没必要特别熟悉 2.关键是..这个编译一次花费的时间太长了..真心感觉有点折腾不起..

于是下了hadoop的编译好的版本..

学习中…

但新问题又来了,每次跑hadoop的命令时,总会出现一个警告,对于一个患有轻微强迫症的人,这是难以忍受的..

经过一番搜索..探查..发现是glibc的版本太低的原因..

阿里云的源上的glibc的最新版本也就是2.12,而hadoop提示需要2.14..

我采取了手动编译更新glibc的方法..然而过程是更加曲折的..这里只说值得记忆的把..

期间把系统弄坏了4次(庆幸阿里云会自动备份磁盘,每次系统坏了只需要回滚磁盘就行了..)..

1.这应该是最菜鸟的错误,把glibc编译并安装到制定好的目录后,我把/lib64/libc.so.6删了(本来打算先删了,然后新建立软连接到libc-2.14.so),结果是悲剧的..

2.借鉴了上次的悲剧,且经过了验证(glibc.so.6只需要在任一个系统库搜索路径存在且有效即可,这个我用我之前的安装的虚拟机测试的..),我把libc安装到了默认的/usr/local下,且在/etc/ld.so.conf中配置了/usr/local/bin目录,然后再删/lib64/libc.so.6,结果仍是悲剧了..(这个具体原因不明..估计因为glibc的版本和ld.so的版本不一致且glibc的路径是通过/etc/ld.so.conf指定的….)

3.借鉴了上次的错误,以为是ld-linux-x86-64.so.2的问题,我先制作软连接/lib/ld-linux-x86-64.so.2,然后删除了/lib64/ld-linux-x86-64.so.2..结果悲剧了..开始报/lib64/ld-linux-x86-64.so.2找不到的错误…

4.借鉴了以上错误,我开始寻求baidu帮助..在一篇博文里,直接将glibc安装到了/usr下(不过貌似他只安装了libc的某些模块),我开始认为,不管怎样,如果只安装libc到/usr下的某些目录,不影响/lib64下面的文件的话,无论如何不会有问题的..事实是悲痛的..貌似安装到/usr会自动把.so文件安装到/lib64下面..结果出现了这样的问题,似乎这次安装libc,把其他的一些.so文件覆盖了旧的,而并没有更新libc.so.6,..所以运行命令要么出现segment fault的问题(不知为什么..),要么是说glibc的版本太低(不是2.14)…

借鉴了以上错误,我开始寻求google帮助..参考http://blog.csdn.net/nameofhsw/article/details/12781905,终于第一次有了比较完整的结果..

但新问题出现了..我的openjdk1.7.0的任何命令的运行时,都没有了任何输出,而改用旧的libc2.12是正常的..

次日..

之前用的java版本openjdk1.7.0,之前因为工作关系,下了一个sun java1.7的rpm包,遂卸载了旧的openjdk,换成sun的试试,结果是一样的..

在网上查不到这样的情况..

突然想到之前学习到的一个linux命令strace,遂strace javac试试..

javac似乎在系统调用futex时停住了…直觉是需要某个信号wake这个进程,在网上查了查,貌似和多线程相关..

发现futex系统调用的第三个参数是一个数字,很像pid,但是我用ps -ef|grep <pid>根本找不到这样的进程…但用ps -ef|grep java时,发现那个pid比javac进程的pid大1…此事必有蹊跷…

用strace -p <那个pid>时,发现也是停在了futex处…这个futex的第三个参数是2…ps -ef发现pid为2的CMD为[kthreadd]…百度一下…貌似说它为内核线程之父…

查看strace javac的输出,发现它运行期间加载了libpthread.so.0,且是从我安装glibc2.14的目录中加载的…

壮着胆..把libpthread.so.0及其指向的真正的.so文件移到了别的地方…结果是幸福的…javac能用了…

注:其实<那个pid>应该是线程的id,可以用ps -eLf查看(LWP列),应该是javac创建的一个线程…

完..