原文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的一个示 例输出如下:
|
假设因为某种原因在升级 glibc的过程中负责用户名 和用户ID转换的库NSS丢失, 我们可以通过把nss库改名来模拟这个环境:
|
这里可以看到, 运行whoami时出现了错 误, ldd程序的输出不会提供有用的帮助:
只会看到whoami依赖Libc.so.6和ld-linux.so.2, 它没有给出运行 whoami所必须的其它库. 这里时用strace跟踪 whoami时的输出:
|
可以发现在不同目录下面查找libnss.so.2的尝 试, 但是都失败了. 如果没有strace这样的工具, 很难发现这个错误是由于缺少动态库造成的. 现在只需要找到libnss.so.2并把它放回 到正确的位置就可以了.
限制strace只跟踪特定的系统调用
如果 已经知道要找什么, 可以让strace只跟踪一些类型的系统调用. 例如, 需要看看在configure脚本里面执行的程序, 需要监视的系统调用就 是execve. 让strace只记录execve的调用用这个命令:
|
部分输出结果为:
已经看到了, strace不仅可以被程序员使用, 普 通系统管理员和用户也可以使用strace来调试系统错误. 必须承认, strace的输出不总是容易理解, 但是很多输出对大多数人来说是不重要 的. 会慢慢学会从大量输出中找到可能需要的信息, 像权限错误, 文件未找到之类的, 那时strace就会成为一个有力的工具了.
--End--