strace命令使用实例

 

      原文http://hi.baidu.com/edeed/blog/item/c59d8d10f362e30a213f2eb8.html

用strace解决库依赖问题

starce 的另一个用处是解决和动态库相关的问题. 当对一个可执行文件运行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的一个示 例输出如下:  


27207 mkdir("/tmp/.ICE-unix", 0777) = -1 EEXIST (File exists)
27207 lstat64("/tmp/.ICE-unix", {st_mode=S_IFDIR|S_ISVTX|0755, st_size=4096, ...}) = 0
27207 unlink("/tmp/.ICE-unix/dcop27207-1066844596") = -1 ENOENT (No such file or directory)
27207 bind(3, {sin_family=AF_UNIX, path="/tmp/.ICE-unix/dcop27207-1066844596"}, 38) = -1 EACCES (Permission denied)
27207 write(2, "_KDE_IceTrans", 13) = 13
27207 write(2, "SocketCreateListener: failed to "..., 46) = 46
27207 close(3) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13
27207 write(2, "SocketUNIXCreateListener: ...Soc"..., 59) = 59
27207 umask(0) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13
27207 write(2, "MakeAllCOTSServerListeners: fail"..., 64) = 64
27207 write(2, "Cannot establish any listening s"..., 39) = 39

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


# whoami
root

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

 

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


# mv /lib/libnss_files.so.2 /lib/libnss_files.so.2.backup
# whoami
whoami: cannot find username for UID 0

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

限制strace只跟踪特定的系统调用

 

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


# ldd /usr/bin/whoami
libc.so.6 => /lib/libc.so.6 (0x4001f000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

 

部分输出结果为:  

 

已经看到了, strace不仅可以被程序员使用, 普 通系统管理员和用户也可以使用strace来调试系统错误. 必须承认, strace的输出不总是容易理解, 但是很多输出对大多数人来说是不重要 的. 会慢慢学会从大量输出中找到可能需要的信息, 像权限错误, 文件未找到之类的, 那时strace就会成为一个有力的工具了. 


--End--
 

你可能感兴趣的:(系统调用,休闲,strace,linux依赖库,linux故障)