工具链

强制升级glibc2.14到2.17问题

2018-06-06  本文已影响0人  MrChenyz

源码编译安装,关键是恢复、比对。备份系统文件,用Live系统恢复原系统状态;比对发行版包管理器软件包的安装路径,移除冲突,比对发行版编译软件包时的编译选项,如果函数库没编译某些特性,可能会导致系统崩溃或已有的应用程序不可用。

pwd /root/linux-3.7 # make INSTALL_HDR_PATH=/root/headers headers_install # pwd /root/glibc-2.17/build $ ../configure --prefix=/usr --enable-add-ons=nptl,libidn --with-headers=/root/headers/include --enable-kernel=3.7.0 $ make $ make install_root=pwd/dest install

pwd

/root/linux-3.7

make INSTALL_HDR_PATH=/root/headers headers_install

pwd

/root/glibc-2.17/build
$ ../configure --prefix=/usr --enable-add-ons=nptl,libidn --with-headers=/root/headers/include --enable-kernel=3.7.0
$ make
$ make install_root=pwd/dest install
warning: 这里如果使用make DESTDIR=...将失效,因为glibc的Makefile是手写的,不是用autotools生成的,DESTDIR是GNU标准,autotools兼容GNU标准
nptl,libidn是为了跟Debian原有的程序兼容

ls dest/usr/lib/librt.so dest/usr/lib/librt.so # ldd /bin/ls | grep librt.so librt.so.1 => /lib/i686/cmov/librt.so.1 (0xb7730000)

ls dest/usr/lib/librt.so

dest/usr/lib/librt.so

ldd /bin/ls | grep librt.so

librt.so.1 => /lib/i686/cmov/librt.so.1 (0xb7730000)

发现不对劲,make install后的glibc,跟系统原来的glibc安装路径不同,这样会导致应用程序使用不同版本的glibc文件而崩溃
调试方法:

make install_root=pwd/dest -p > /tmp/make $ dpkg -S librt.so libc6-dev: /usr/lib/librt.so libc6: /lib/librt.so.1 libc6-i686: /lib/i686/cmov/librt.so.1 # apt-get remove libc6-i686

make install_root=pwd/dest -p > /tmp/make

$ dpkg -S librt.so
libc6-dev: /usr/lib/librt.so
libc6: /lib/librt.so.1
libc6-i686: /lib/i686/cmov/librt.so.1

apt-get remove libc6-i686

启发: 源码编译后,安装前,要查看比对发行版软件包管理器已安装的相关软件包的路径

接着,通过比对dest/和系统软件包的安装路径,备分系统重要的文件夹,以便系统崩溃后,用U盘里的GNU/Linux恢复系统
比对:

cat /tmp/diff.sh #! /bin/bash destdir=$1 pkg=$2 list=/tmp/list.diff pkglist=/tmp/list.pkg backupdir="/backup/pkg" answer=n if [ x"$destdir" == x -o x"$pkg" == x ] ; then echo "Usage: diff.sh destdir debian-pkg" exit 1 fi dpkg -L $pkg 2>&1 1>/dev/null if [ $? -ne 0 ] ; then echo "error: $pkg doesn't exists." exit 1 fi echo -n "backup $pkg to $backupdir/$pkg.tar?(y/[n])" read -N 1 -t 5 answer echo rm -f $list $pkglist for name in dpkg -L $pkg do if [ ! -e $destdir/$name -a -f $name ] ; then echo $name | tee -a $list fi if [ x$answer == x"y" -a -f $name ] ; then echo $name >> $pkglist fi done mkdir -p $backupdir tar cf $backupdir/$pkg.diff.tar -T $list 2>/dev/null if [ x$answer == x"y" ] ; then tar cf $backupdir/$pkg.pkg.tar -T $pkglist 2>/dev/null fi # /tmp/diff.sh dest/ libc6 # /tmp/diff.sh dest/ libc6-dev

cat /tmp/diff.sh

! /bin/bash

destdir=$1
pkg=$2
list=/tmp/list.diff
pkglist=/tmp/list.pkg
backupdir="/backup/pkg"
answer=n
if [ x"$destdir" == x -o x"$pkg" == x ] ; then
echo "Usage: diff.sh destdir debian-pkg"
exit 1
fi
dpkg -L $pkg 2>&1 1>/dev/null
if [ $? -ne 0 ] ; then
echo "error: $pkg doesn't exists."
exit 1
fi

echo -n "backup $pkg to $backupdir/$pkg.tar?(y/[n])"
read -N 1 -t 5 answer
echo
rm -f $list $pkglist
for name in dpkg -L $pkg
do
if [ ! -e $destdir/$name -a -f $name ] ; then
echo $name | tee -a $list
fi
if [ x$answer == x"y" -a -f $name ] ; then
echo $name >> $pkglist
fi
done
mkdir -p $backupdir
tar cf $backupdir/$pkg.diff.tar -T $list 2>/dev/null
if [ x$answer == x"y" ] ; then
tar cf $backupdir/$pkg.pkg.tar -T $pkglist 2>/dev/null
fi

/tmp/diff.sh dest/ libc6

/tmp/diff.sh dest/ libc6-dev

备份:

ls dest/ etc lib sbin usr var # du -sh /etc/ /lib/ /sbin/ /usr/ /var/ # mkdir /backup # cp -R /etc/ /lib/ /sbin/ /usr/ /var/ /backup/

ls dest/

etc lib sbin usr var

du -sh /etc/ /lib/ /sbin/ /usr/ /var/

mkdir /backup

cp -R /etc/ /lib/ /sbin/ /usr/ /var/ /backup/

假想要进行的安装:

make install # while read name > do > rm -f $name > done < /tmp/list.diff

make install

while read name

do
rm -f $name
done < /tmp/list.diff
出现错误:

test ! -x /root/glibc-2.17/build/elf/ldconfig || LC_ALL=C LANGUAGE=C \ /root/glibc-2.17/build/elf/ldconfig \ /lib /usr/lib LD_SO=ld-linux.so.2 CC="gcc" /usr/bin/perl scripts/test-installation.pl /root/glibc-2.17/build/ Segmentation fault make[1]: *** [install] Error 139 make[1]: Leaving directory `/root/glibc-2.17' make: *** [install] 错误 2 #

test ! -x /root/glibc-2.17/build/elf/ldconfig || LC_ALL=C LANGUAGE=C
/root/glibc-2.17/build/elf/ldconfig
/lib /usr/lib
LD_SO=ld-linux.so.2 CC="gcc" /usr/bin/perl scripts/test-installation.pl /root/glibc-2.17/build/
Segmentation fault
make[1]: *** [install] Error 139
make[1]: Leaving directory `/root/glibc-2.17'
make: *** [install] 错误 2

试验正常的安装方法:
如果是编译安装比系统低版本的glibc,要用tar方式安装,然后删除/tmp/list.diff里的文件,再ldconfig。
这里我估计/lib/libc.so.6这些链接文件链接的是原来系统的库文件,所以要用tar方式覆盖以指向新的库文件,否则删除顺序出错,可能导致找不到函数库而导致系统崩溃,还没去做实验证实(懒)。ldconfig会链接高版本的函数库到系统。遇到问题用tar安装是非常好用的方法。这个方法也可以用来安装高版本glibc。

init 1 # cd dest # tar cf - . | (cd / && tar xf -) # while read name > do > rm -f $name > done < /tmp/list.diff # ldconfig -v

init 1

cd dest

tar cf - . | (cd / && tar xf -)

while read name

do
rm -f $name
done < /tmp/list.diff

ldconfig -v

如果是编译安装比系统高版本的glibc

init 1 # make install segment fault # ldconfig -v # make install

init 1

make install

segment fault

ldconfig -v

make install

warning: 不要用那个rm -f $name的/tmp/list.diff方法,目前不知道为什么会失败,难道是glibc的idn add on没装?
这里还有个问题glibc依赖特定版本的gcc和kernel吗?
如果make install的安装方法不成功,就用tar的方法安装吧,make install后面有个check,要测试不少东西,跟binutils, gcc, linux的版本都有关系。

上面那篇IBM文章的作者说,编译安装glibc建议在runlevel 1中进行,直接安装会出错,需要重启系统纠正关系链,如果重启系统仍出错,用U盘的Live系统手动纠正关系链或恢复系统
如果能正常重启系统,进入glibc再make install一次,这次安装通过的话就算安装成功了

验证:

ldd /bin/ls libc.so.6 => /lib/libc.so.6 (0xb76fb000) # ls -l /lib/libc.so.6 lrwxrwxrwx 1 root root 12 1月 5 11:55 /lib/libc.so.6 -> libc-2.17.so # /lib/libc.so.6 GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al. Compiled by GNU CC version 4.4.5. Compiled on a Linux 2.6.39 system on 2013-01-05. # man ls

ldd /bin/ls

libc.so.6 => /lib/libc.so.6 (0xb76fb000)

ls -l /lib/libc.so.6

lrwxrwxrwx 1 root root 12 1月 5 11:55 /lib/libc.so.6 -> libc-2.17.so

/lib/libc.so.6

GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Compiled by GNU CC version 4.4.5.
Compiled on a Linux 2.6.39 system on 2013-01-05.

man ls

昨晚在irc.freenode.net上的glibc channel,询问一位IBM glibc开发者,关于glibc开发和编译的事,记录如下:

上一篇 下一篇

猜你喜欢

热点阅读