使用strace命令解决linux服务器依赖库问题

使用strace命令解决linux服务器依赖库问题

简单说明:
strace的另一个用处是解决和动态库相关的问题。当对一个可执行文件运行ldd时,它会告诉你程序使用的动态库和找到动态库的位置。但是如果你正在使用一个比较老 的glibc版本(2.2或更早),你可能会有一个有bug的ldd程序,它可能会报告在一个目录下发现一个动态库,但是真正运行程序时动态连接程序 (/lib/ld-linux.so.2)却可能到另外一个目录去找动态连接库。这通常因为/etc/ld.so.conf和 /etc/ld.so.cache文件不一致,或者/etc/ld.so.cache被破坏。在glibc 2.3.2版本上这个错误不会出现,可能ld-linux的这个bug已经被解决了。

尽管这样,ldd并不能把所有程序依赖的动态库列出 来,系统调用dlopen可以在需要的时候自动调入需要的动态库,而这些库可能不会被ldd列出来。作为glibc的一部分的NSS(Name Server Switch)库就是一个典型的例子,NSS的一个作用就是告诉应用程序到哪里去寻找系统帐号数据库。应用程序不会直接连接到NSS库,glibc则会通 过dlopen自动调入NSS库。如果这样的库偶然丢失,你不会被告知存在库依赖问题,但这样的程序就无法通过用户名解析得到用户ID了。
让我们看一个例子:
whoami程序会给出你自己的用户名,这个程序在一些需要知道运行程序的真正用户的脚本程序里面非常有用,whoami的一个示例 输出如下:
[root@mgr04 opt]# whoami
root

whoami程序会给出你自己的用户名,这个程序在一些需要知道运行程序的真正用户的脚本程序里面非常有用,whoami的一个示例 输出如下:

特别提示:演示系统环境如下

[root@mgr04 opt]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core) 

在centos系统命令行运行 ldd /usr/bin/whoami只能查看到whoami才依赖了2个库文件,然而实际上whoami 命令依赖系统的库文件远不止这些。

[root@mgr04 opt]# ldd /usr/bin/whoami
    linux-vdso.so.1 =>  (0x00007ffd1c111000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fe374d4d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fe375116000)

咱们可以通过 strace -e trace=open whoami 命令来查看实际中whoami 所调用的库文件如下:

查看命令行执行whoami命令是都打开了系统哪些依赖库文件:
[root@mgr04 opt]# strace -e trace=open whoami
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
root
+++ exited with 0 +++

故障模拟演示:
假设因为某种原因在升 级glibc的过程中负责用户名和用户ID转换的库NSS丢失,我们可以通过把nss库改名来模拟这个环境

[root@mgr04 opt]# mv /lib64/libnss_files.so.2 /lib64/libnss_files.so.2.bak
[root@mgr04 opt]#
[root@mgr04 opt]# whoami
whoami: cannot find name for user ID 0
[root@mgr04 opt]# 

这里你可以看到,运行whoami时出现了错误,此时在命令行执行ldd程序的输出不会提供有用的帮助:

[root@mgr04 opt]# ldd /usr/bin/whoami
    linux-vdso.so.1 =>  (0x00007ffd62bd4000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fdcf861f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fdcf89e8000)
[root@mgr04 opt]# 

你只会看到whoami依赖Libc.so.6和ld-linux-x86-64.so.2,它没有给出运行whoami所必须的其他库。这里时用strace跟踪 whoami时的输出:

[root@mgr04 opt]# strace -o whoami-strace.txt whoami
whoami: cannot find name for user ID 0
[root@mgr04 opt]# cat whoami-strace.txt
.....................
.....................
socket(AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1717, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f306e2ae000
read(3, "#\n# /etc/nsswitch.conf\n#\n# An ex"..., 4096) = 1717
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f306e2ae000, 4096)            = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=28446, ...}) = 0
mmap(NULL, 28446, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f306e2a8000
close(3)                                = 0
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib64/tls/x86_64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib64/tls/x86_64", 0x7fff92c1f600) = -1 ENOENT (No such file or directory)
open("/lib64/tls/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib64/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
open("/lib64/x86_64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib64/x86_64", 0x7fff92c1f600)   = -1 ENOENT (No such file or directory)
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib64", {st_mode=S_IFDIR|0555, st_size=32768, ...}) = 0
open("/usr/lib64/tls/x86_64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/tls/x86_64", 0x7fff92c1f600) = -1 ENOENT (No such file or directory)
open("/usr/lib64/tls/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
open("/usr/lib64/x86_64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/x86_64", 0x7fff92c1f600) = -1 ENOENT (No such file or directory)
open("/usr/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64", {st_mode=S_IFDIR|0555, st_size=32768, ...}) = 0
munmap(0x7f306e2a8000, 28446)           = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=28446, ...}) = 0
mmap(NULL, 28446, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f306e2a8000
close(3)                                = 0
open("/lib64/tls/libnss_sss.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib64/libnss_sss.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib64/tls/libnss_sss.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib64/libnss_sss.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
munmap(0x7f306e2a8000, 28446)           = 0
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2502, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f306e2ae000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2502
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f306e2ae000, 4096)            = 0
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "whoami: cannot find name for use"..., 39) = 39
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
[root@mgr04 opt]# 

你可以发现在不同目录下面查找libnss.so.2的尝试,但是都失败了。如果没有strace这样的工具,很难发现这个错误是由于缺少动态库造成的。现 在只需要找到libnss.so.2并把它放回到正确的位置就可以了。 

如果你已经知道你要找什么,你可以让strace只跟踪一些类型的系统调用。例如,你需要看看在configure脚本里面执行的程序,你需要监视的系统调 用就是execve。让strace只记录execve的调用用这个命令:

strace -f -o configure-strace.txt -e execve ./configure

原文地址:
https://www.linuxidc.com/Linux/2012-12/75671p3.htm

原文地址:https://blog.51cto.com/wujianwei/2368199

时间: 2024-07-28 17:01:12

使用strace命令解决linux服务器依赖库问题的相关文章

使用解决linux服务器依赖库问题

strace的另一个用处是解决和动态库相关的问题.当对一个可执行文件运行ldd时,它会告诉你程序使用的动态库和找到动态库的位置.但是如果你正在使用一个比较老 的glibc版本(2.2或更早),你可能会有一个有bug的ldd程序,它可能会报告在一个目录下发现一个动态库,但是真正运行程序时动态连接程序 (/lib/ld-linux.so.2)却可能到另外一个目录去找动态连接库.这通常因为/etc/ld.so.conf和 /etc/ld.so.cache文件不一致,或者/etc/ld.so.cache

小黑的日常折腾-复制外部命令的可执行文件和依赖库文件到指定目录下的对应目录

清明三天假期基本都是在写脚本中度过了,今天又折腾了一个新的脚本,该脚本的作用是快速复制一个或多个命令的可执行文件和依赖库文件到一个模拟的根文件系统下的相应目录下,这个脚本平时运维估计用不到,只有自己制作一个小的Linux发行版时才有可能使用该脚本. 脚本具体的功能如下: 1)提示用户选择要从文本中读取要复制的命令名还是从当前终端中交互式输入命令名. 2)用户选择前者,会自动使用vim打开一个文件,用户根据格式说明填入要复制的命令的名称,可以是多个命令,保存退出后自动执行复制操作. 3)用户选择后

lld解决程序启动依赖库的问题

场景说明:查找程序依赖库是非常麻烦的,如果需要的又是一些不长使用的库,对于整个系统的移植是非常苦难的.目前尝试使用lld去查找所有依赖的库,然后将这些依赖的库提取,放在同一个文件夹中,然后制定依赖的路径,解决问题. Ldd [选项] 文件 选项有-v:打印ldd 的版本号:-d:执行符号重部署,并报告缺少的目标对象(只对ELF 格式适用):-r:对目标对象和函数执行重新部署,并报告缺少的目标对象和函数(只对ELF 格式适用):-h:帮助信息. 执行如下命令来查看应用程序所关联的库: Ldd –v

删除Linux的依赖库并进入救援模式恢复

删除Linux的依赖库并进入救援模式恢复 模拟一下依赖库文件被删,并进入救援模式恢复 系统:CentOS7 一.删除mv的依赖库文件 删除/lib64/libc.so.6 [[email protected] Packages]# which mv alias mv='mv -i' /usr/bin/mv [[email protected] Packages]# ldd /usr/bin/mv linux-vdso.so.1 => (0x00007ffd51946000) libselinux

解决linux服务器乱码

解决linux服务器乱码: 1.vim /etc/profile 2.在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL 的上一行新增:LANG="en_US.UTF-8" 3.在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL 最后新增 LANG. 4.刷新环境变量http://stevenfeng.iteye.com/blog/1886201生

使用Free命令查看Linux服务器内存使用状况(-/+ buffers/cache详解)

free命令可选参数 -b,-k,-m,-g show output in bytes, KB, MB, or GB -h human readable output (automatic unit scaling) -l show detailed low and high memory statistics -o use old format (no -/+buffers/cache line) -t display total for RAM + swap -s update every

nc命令在Linux服务器之间互传文件或文件夹

有时候,在线上服务器上传文件或文件夹,没有做秘钥,也不知道用户的相关密码,scp和rsync都使用不了. 推荐使用nc命令在Linux服务器之间互传,条件是互相能ping通. 文件夹: 接受文件的服务器 nc -l 9995 | tar zxvf - (可以先获取本地内网ip-1.1.1.1,稍后需要复制到另外一条服务器上,9995端口保持一致即可,可随意)文件所在的服务器 tar zcvf - 文件名称/* | nc 1.1.1.1 9995 文件:接收端 nc -l 1234 > abc.l

linux下依赖库的版本问题引起的安装失败:libssl-dev版本问题无法安装 :libssl-dev : 依赖: libssl1.0.0 (= 1.0.1-4ubuntu3) 但是 1.0.1-4ubuntu5.31 正要被安装

依赖库版本问题引起的安装失败解决方法如下有两种: 1.是由于源需要更新,如下操作: libssl-dev : 依赖: libssl0.9.8 (= 0.9.8o-1ubuntu4) 但是 0.9.8o-1ubuntu4.4 正要被安装 解决方法 进入“系统->系统管理->更新管理器->设置”,在弹出的“软件源”对话框中选“更新”标签页,选中“Ubuntu 更新”下面的四个复选框,关闭后 在终端先执行“sudo apt-get update”就ok了. 转自:http://baalwolf

解决Linux服务器更换IP后,ssh连接被拒绝问题

解决更换Linux服务器IP后,ssh登录报“ssh: connect to host xxx port 22: Connection refused”错误 由于之前服务器的sshd服务一直正常,但更换IP后通过putty进行登录,报“连接被拒绝”异常 一.重启sshd服务,查看登录是否正常,如果还有异常进行下面步骤 netstat sshd 二.将.ssh/known_hosts文件里面的IP地址修改正确 1.vi ~/.ssh/known_hosts 2.将老IP地址全部替换在新的IP地址