在讲解case之前,需要首先讲解ldd命令:
ldd到底是做什么的?
ldd用来输出二进制可执行文件或者库文件的依赖;它本是一个script, 并不是binary 文件,其本质上只是设置了环境变量: D_TRACE_LOADED_OBJECTS、LD_WARN、LD_BIND_NOW、LD_LIBRARY_VERSION、LD_VERBOSE(请参考ldd脚本文件的内容查看具体设置的环境变量)等。当通过export LD_TRACE_LOADED_OBJECTS=VALUE设置变量(该变量的值无所谓)后,那么无论执行任何的二进制可执行文件:都会显示该二进制文件对应的依赖;其效果和ldd 命令一样;
那么为什么设置了上述变量之后,可执行的二进制文件就变成显示 对应的依赖呢?
因为二进制文件被调用之前,优先调用了系统的/lib/ld-linux.so.2,这个动态库是一个可执行文件;该动态库运行的时候根据设置的环境变量,选择 显示的属性:可执行文件对应的依赖;所以其实是ld-linux.so.2这个模块把可执行二进制文件或者库文件的依赖显示出来了;
- 如果我们运行ld-linux.so.2这个模块,发现有一个--list参数,对于模块文件,我们除了用 ldd命令,也可以用ld-linux.so.2 --list MODILE_FILE_PATH 来显示依赖;
- 对于二进制可执行文件,也有两种方式来显示依赖: ldd命令,以及 用export LD_TRACE_LOADED_OBJECTS 设置变量后,直接执行二进制文件;
用ldd命令可以成功列出文件的依赖,那么就有办法来排除文件crash导致的问题,下面用一个case来介绍大致的处理过程:
文件crash通常会出现的现象有: core dump 提示, segment fatal 错误提示等;对于这些错误,很多情况下是文件的crash导致的;这时候要找出发生了错误的文件,然后进行修复:
问题出现:
[root@www ~]# rpcbind
Segmentation fault (core dumped)
[root@www ~]#
调用ldd命令来显示依赖:
[root@www ~]# ldd `which rpcbind`
linux-vdso.so.1 => (0x00007ffe87db4000)
libtirpc.so.1 => /lib64/libtirpc.so.1 (0x00007f90e624f000)
libsystemd.so.0 => /lib64/libsystemd.so.0 (0x00007f90e601e000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f90e5e02000)
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f90e5bf7000)
libc.so.6 => /lib64/libc.so.6 (0x00007f90e582a000)
libcap.so.2 => /lib64/libcap.so.2 (0x00007f90e5625000)
libm.so.6 => /lib64/libm.so.6 (0x00007f90e5323000)
librt.so.1 => /lib64/librt.so.1 (0x00007f90e511b000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f90e4ef4000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f90e4cce000)
liblz4.so.1 => /lib64/liblz4.so.1 (0x00007f90e4ab9000)
libgcrypt.so.11 => /lib64/libgcrypt.so.11 (0x00007f90e4838000)
libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007f90e4633000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f90e441a000)
libdw.so.1 => /lib64/libdw.so.1 (0x00007f90e41cb000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f90e3fc7000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f90e3db1000)
/lib64/ld-linux-x86-64.so.2 (0x00007f90e6689000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f90e3b97000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007f90e3992000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f90e3730000)
libelf.so.1 => /lib64/libelf.so.1 (0x00007f90e3518000)
libz.so.1 => /lib64/libz.so.1 (0x00007f90e3302000)
libbz2.so.1 => /lib64/libbz2.so.1 (0x00007f90e30f2000)
[root@www ~]#
对上述的文件,验证其完整性,怎么做呢?
如果这个文件是rpm包提供的,那么可以通过rpm -V PACKAGE 来验证文件的完整性;
这里省略验证的命令(用组合命令一条就可以实现,自己试下吧!),结果如下:
image.png
在上面的结果中,可以发现 /lib64/libtirpc.so.1.0.10 这个文件的大小(S)以及修改时间(M)发生了变化,而这个文件是一个库文件,所以大小发生变化很值得怀疑;
重新安装这个文件所在的包,然后解决问题.
思考:
这个case是可以reproduce的,那么你怎么来手动破坏一个命令/服务,然后用上述的思路来解决呢?
提示: 用lsof 的结果来统计库文件都被哪些进程在使用,比如上面的/lib64/libtirpc.so.1.0.10, 统计之后就发现:只有rpcbind使用这个库文件,所以破坏这个库文件,那么有且只有rpcbind命令不能正常工作;剩下的就是按照上面的思路进行fix了哦!之所以要统计lsof的结果,以防止破坏了系统中影响面很大的库文件,毕竟只是为了学习嘛,达到目的即可.
网友评论