问题
昨天在公司的一台公共服务器上安装了iperf3时,在进行到post-install阶段的libc-bin的trigger阶段后,报告各种失败。然后执行任何命令都直接报Segmentation fault (core dumped)
。尝试重启服务器,无法正常启动。插上显示器后发现,在grub2菜单中无论正常进入或使用recovery mode进入都会报Kernel panic - not syncing: Attempted to kill init exitcode=0x000000b
,调用栈没有什么参考价值。
那该如何解决呢?
排查
首先考虑是不是长时间运行磁盘有逻辑错误,需要检查清理下。于是找了一个U盘做的ubuntu 20.04的live-cd,首先使用fsck.ext4
检查问题分区/dev/sda1
,报告为没有任何问题。那这方面的问题就排除掉了。
接下来就看看是不是apt安装了错误的包。挂载/dev/sda1
到~/haha2
,chroot切换到问题的rootfs重新安装正确的包来解决。没想到在首先通过mount挂载好/dev
, /dev/pts
, /proc
, 以及/sys
之后,执行切换rootfs的动作
1 2 3 |
root@ubuntu:~/haha2 chroot . /bin/bash Segmentation fault (core dumped) |
诶,好像找到点门道了。连切换进入rootfs都会产生问题,那大概率是libc相关的文件存在问题了。
解决
第一次解决
因为没有对比,所以具体是哪个或哪些文件出问题其实不容易确定。那怎么办呢? 不要紧。我们可以把基础系统都换掉。这里要用到的是debootstrap
这个工具,可以在指定目录下构建起一套可以使用的基于debian
的rootfs。执行以下命令
1 2 |
root@ubuntu:~/haha2 debootstrap --variant=minibase trusty . http://archive.ubuntu.com/ubuntu/ |
这一步是重建了整个基础rootfs,因此一定包括libc系列的文件。然后再次使用chroot尝试进入,成功了!
但修复还没有结束。这次只是能chroot进来了,但是dpkg管理的软件包系统还没有恢复。因为管理包记录的/var/lib/dpkg
已经被debootstrap覆盖掉了。这里使用之前的备份文件进行修复,将/var/backups/dpkg.status.0
拷贝覆盖掉/var/lib/dpkg/status
这个文件,恢复之前的安装记录。然后再次运行apt-get update
重新获取可用软件包,apt-get -f install
再次继续恢复上次没有完成的安装。
神奇的事情再次发生,又运行到了post-install阶段的libc-bin的trigger阶段后,apt命令又报错退出了。再次执行各种命令,还是Segmentation fault (core dumped)
。这个系统是怎么了?
第二次解决
看来还是得沉下心来好好找找问题。于是仔细看了下/lib/x86_64-linux-gnu/
下的文件。赫然发现在一堆glibc 2.19的文件中有一个libc-2.23.so,并且libc.so.6的软连接指向的是libc-2.23.so。
1 2 3 4 5 6 |
root@ubuntu:~/haha2/lib/x86_64-linux-gnu# ls -al libc* -rwxr-xr-x 1 root root 1857312 Mar 27 2019 libc-2.19.so -rwxr-xr-x 1 root root 1868984 Jan 15 2018 libc-2.23.so lrwxrwxrwx 1 root root 12 Apr 17 02:47 libc.so.6 -> libc-2.23.so ... |
这应当是真正原因! libc.so.6指向了glibc2.23版本,但其他的配合库文件都是2.19版本的,因此出现了问题。解决方法也很简单,暂时先把libc-2.23.so替换成指向libc-2.19.so的软链,保证apt过程可以正常跑
1 2 3 4 5 6 |
root@ubuntu:~/haha2/lib/x86_64-linux-gnu# ls -al libc* -rwxr-xr-x 1 root root 1857312 Mar 27 2019 libc-2.19.so lrwxrwxrwx 1 root root 12 Apr 17 02:55 libc-2.23.so -> libc-2.19.so lrwxrwxrwx 1 root root 12 Apr 17 02:47 libc.so.6 -> libc-2.23.so ... |
接下来进行修复即可。再次进入chroot环境,使用apt upgrade将所有pending的安装执行完,然后执行
1 2 |
root@duobeivmh2:/ apt-get install --reinstall libc-bin |
完成后,再次确认,发现在trigger这步,指向libc.so.6的软链接没有再变化指向到2.23版本了。然后重启,修改服务器启动第一顺序为内置磁盘,拔掉livecd U盘,机器正常启动。尝试使用apt安装了一个新的包,没有出现Segmentation fault (core dumped)
。至此问题解决。
总结
到目前为止,基本可以确定,之前的问题是有同事尝试替换系统的libc导致的问题。可能是强制用dpkg安装了不正确的deb包所导致问题,然后再出问题之后,仅仅是手工修改了软链将libc.so.6的指向更改为2.19,但是没有重新安装回正确的包。所以结果就是只要再次运行apt-get安装任何包,在trigger这步就一定跪掉。
本次问题排查让我明确了dpkg的包管理机制,并应用了之前就熟悉的chroot和deboostrap工具,算是有所收获。
回想起之前每次加深对于linux发行版的认识,基本都是来自于解决一些自己平常折腾出来的奇奇怪怪的问题。仔细排查解决而不是重装了之,既最大限度的保护了数据,又解决了问题本身。
在条件允许的情况下勇于战略进攻直面问题,方能得到更多收获。
在条件不允许的情况下勇于战术撤退绕过问题,方能得到更多成果。