使用truss、strace或ltrace诊断软件问题

2023-10-29

         进程无法启动,软件运行速度突然变慢,程序的"Segment Fault"等等都是让每个Unix系统用户头痛的问题,本文通过三个实际案例演示如何使用truss、strace和ltrace这三个常用的调试工具来快速诊断软件的"疑难杂症"。


    truss和strace用来跟踪一个进程的系统调用或信号产生的情况,而 ltrace用来跟踪进程调用库函数的情况。truss是早期为System V R4开发的调试程序,包括Aix、FreeBSD在内的大部分Unix系统都自带了这个工具;而strace最初是为SunOS系统编写的,ltrace最早出现在GNU/Debian Linux中。这两个工具现在也已被移植到了大部分Unix系统中,大多数Linux发行版都自带了strace和ltrace,而FreeBSD也可通过Ports安装它们。

    你不仅可以从命令行调试一个新开始的程序,也可以把truss、strace或ltrace绑定到一个已有的PID上来调试一个正在运行的程序。三个调试工具的基本使用方法大体相同,下面仅介绍三者共有,而且是最常用的三个命令行参数:

-f :除了跟踪当前进程外,还跟踪其子进程。
-o file :将输出信息写到文件file中,而不是显示到标准错误输出(stderr)。
-p pid :绑定到一个由pid对应的正在运行的进程。此参数常用来调试后台进程。

    使用上述三个参数基本上就可以完成大多数调试任务了,下面举几个命令行例子:


truss -o ls.truss ls -al: 跟踪ls -al的运行,将输出信息写到文件/tmp/ls.truss中。
strace -f -o vim.strace vim: 跟踪vim及其子进程的运行,将输出信息写到文件vim.strace。
ltrace -p 234: 跟踪一个pid为234的已经在运行的进程。

    三个调试工具的输出结果格式也很相似,以strace为例:

brk(0)                                  = 0x8062aa8
brk(0x8063000)                          = 0x8063000
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0x92f) = 0x40016000


    每一行都是一条系统调用,等号左边是系统调用的函数名及其参数,右边是该调用的返回值。 truss、strace和ltrace的工作原理大同小异,都是使用ptrace系统调用跟踪调试运行中的进程,详细原理不在本文讨论范围内,有兴趣可以参考它们的源代码。

举两个实例演示如何利用这三个调试工具诊断软件的"疑难杂症":


案例一:运行clint出现Segment Fault错误

    操作系统:FreeBSD-5.2.1-release

    clint是一个C++静态源代码分析工具,通过Ports安装好之后,运行:



# clint foo.cpp
Segmentation fault (core dumped)



    在Unix系统中遇见"Segmentation Fault"就像在MS Windows中弹出"非法操作"对话框一样令人讨厌。OK,我们用truss给clint"把把脉":


# truss -f -o clint.truss clint
Segmentation fault (core dumped)
# tail clint.truss
  739: read(0x6,0x806f000,0x1000)               = 4096 (0x1000)
  739: fstat(6,0xbfbfe4d0)                       = 0 (0x0)
  739: fcntl(0x6,0x3,0x0)                        = 4 (0x4)
  739: fcntl(0x6,0x4,0x0)                        = 0 (0x0)
  739: close(6)                                    = 0 (0x0)
  739: stat("/root/.clint/plugins",0xbfbfe680)   ERR#2 'No such file or directory'
SIGNAL 11
SIGNAL 11
Process stopped because of:  16
process exit, rval = 139



    我们用truss跟踪clint的系统调用执行情况,并把结果输出到文件clint.truss,然后用tail查看最后几行。注意看clint执行的最后一条系统调用(倒数第五行):stat("/root/.clint/plugins",0xbfbfe680) ERR#2 'No such file or directory',问题就出在这里:clint找不到目录"/root/.clint/plugins",从而引发了段错误。怎样解决?很简单:mkdir -p /root/.clint/plugins,不过这次运行clint还是会"Segmentation Fault"9。继续用truss跟踪,发现clint还需要这个目录"/root/.clint/plugins/python",建好这个目录后clint终于能够正常运行了。

案例二:vim启动速度明显变慢


    操作系统:FreeBSD-5.2.1-release

    vim版本为6.2.154,从命令行运行vim后,要等待近半分钟才能进入编辑界面,而且没有任何错误输出。仔细检查了.vimrc和所有的vim脚本都没有错误配置,在网上也找不到类似问题的解决办法,难不成要hacking source code?没有必要,用truss就能找到问题所在:



# truss -f -D -o vim.truss vim



    这里-D参数的作用是:在每行输出前加上相对时间戳,即每执行一条系统调用所耗费的时间。我们只要关注哪些系统调用耗费的时间比较长就可以了,用less仔细查看输出文件vim.truss,很快就找到了疑点:

735: 0.000021511 socket(0x2,0x1,0x0)       = 4 (0x4)
735: 0.000014248 setsockopt(0x4,0x6,0x1,0xbfbfe3c8,0x4) = 0 (0x0)
735: 0.000013688 setsockopt(0x4,0xffff,0x8,0xbfbfe2ec,0x4) = 0 (0x0)
735: 0.000203657 connect(0x4,{ AF_INET 10.57.18.27:6000 },16) ERR#61 'Connection refused'
735: 0.000017042 close(4)          = 0 (0x0)
735: 1.009366553 nanosleep(0xbfbfe468,0xbfbfe460) = 0 (0x0)
735: 0.000019556 socket(0x2,0x1,0x0)       = 4 (0x4)
735: 0.000013409 setsockopt(0x4,0x6,0x1,0xbfbfe3c8,0x4) = 0 (0x0)
735: 0.000013130 setsockopt(0x4,0xffff,0x8,0xbfbfe2ec,0x4) = 0 (0x0)
735: 0.000272102 connect(0x4,{ AF_INET 10.57.18.27:6000 },16) ERR#61 'Connection refused'
735: 0.000015924 close(4)          = 0 (0x0)
735: 1.009338338 nanosleep(0xbfbfe468,0xbfbfe460) = 0 (0x0)


vim试图连接10.57.18.27这台主机的6000端口(第四行的connect()),连接失败后,睡眠一秒钟继续重试(第6行的nanosleep())。以上片断循环出现了十几次,每次都要耗费一秒多钟的时间,这就是vim明显变慢的原因。可是,你肯定会纳闷:"vim怎么会无缘无故连接其它计算机的6000端口呢?"。问得好,那么请你回想一下6000是什么服务的端口?没错,就是X Server。看来vim是要把输出定向到一个远程X Server,那么Shell中肯定定义了DISPLAY变量,查看.cshrc,果然有这么一行:setenv DISPLAY ${REMOTEHOST}:0,把它注释掉,再重新登录,问题就解决了。


案例三:用调试工具掌握软件的工作原理

    操作系统:Red Hat Linux 9.0


    用调试工具实时跟踪软件的运行情况不仅是诊断软件"疑难杂症"的有效的手段,也可帮助我们理清软件的"脉络",即快速掌握软件的运行流程和工作原理,不失为一种学习源代码的辅助方法。下面这个案例展现了如何使用strace通过跟踪别的软件来"触发灵感",从而解决软件开发中的难题的。


    大家都知道,在进程内打开一个文件,都有唯一一个文件描述符(fd:file descriptor)与这个文件对应。而本人在开发一个软件过程中遇到这样一个问题:已知一个fd ,如何获取这个fd所对应文件的完整路径?不管是Linux、FreeBSD或是其它Unix系统都没有提供这样的API,怎么办呢?我们换个角度思考:Unix下有没有什么软件可以获取进程打开了哪些文件?如果你经验足够丰富,很容易想到lsof,使用它既可以知道进程打开了哪些文件,也可以了解一个文件被哪个进程打开。好,我们用一个小程序来试验一下lsof,看它是如何获取进程打开了哪些文件。

/* testlsof.c */
#include 
#include 
#include 
#include 
#include 

int main(void)
{
        open("/tmp/foo", O_CREAT|O_RDONLY);    /* 打开文件/tmp/foo */
        sleep(1200);                                /* 睡眠1200秒,以便进行后续操作 */
        return 0;
}



    将testlsof放入后台运行,其pid为3125。命令lsof -p 3125查看进程3125打开了哪些文件,我们用strace跟踪lsof的运行,输出结果保存在lsof.strace中:

# gcc testlsof.c -o testlsof
# ./testlsof &
[1] 3125
# strace -o lsof.strace lsof -p 3125


    我们以"/tmp/foo"为关键字搜索输出文件lsof.strace,结果只有一条:


# grep '/tmp/foo' lsof.strace
readlink("/proc/3125/fd/3", "/tmp/foo", 4096) = 8


 原来lsof巧妙的利用了/proc/nnnn/fd/目录(nnnn为pid):Linux内核会为每一个进程在/proc/建立一个以其pid为名的目录用来保存进程的相关信息,而其子目录fd保存的是该进程打开的所有文件的fd。目标离我们很近了。好,我们到/proc/3125/fd/看个究竟:

# cd /proc/3125/fd/
# ls -l
total 0
lrwx------    1 root     root           64 Nov  5 09:50 0 -> /dev/pts/0
lrwx------    1 root     root           64 Nov  5 09:50 1 -> /dev/pts/0
lrwx------    1 root     root           64 Nov  5 09:50 2 -> /dev/pts/0
lr-x------    1 root     root           64 Nov  5 09:50 3 -> /tmp/foo
# readlink /proc/3125/fd/3
/tmp/foo



    答案已经很明显了:/proc/nnnn/fd/目录下的每一个fd文件都是符号链接,而此链接就指向被该进程打开的一个文件。我们只要用readlink()系统调用就可以获取某个fd对应的文件了,代码如下:


#include 
#include 
#include 
#include 
#include 
#include 
int get_pathname_from_fd(int fd, char pathname[], int n)
{
        char buf[1024];
        pid_t  pid;
        bzero(buf, 1024);
        pid = getpid();
        snprintf(buf, 1024, "/proc/%i/fd/%i", pid, fd);
        return readlink(buf, pathname, n);
}
int main(void)
{
        int fd;
        char pathname[4096];
        bzero(pathname, 4096);
        fd = open("/tmp/foo", O_CREAT|O_RDONLY);
        get_pathname_from_fd(fd, pathname, 4096);
        printf("fd=%d; pathname=%sn", fd, pathname);
        return 0;
}


    出于安全方面的考虑,在FreeBSD 5 之后系统默认已经不再自动装载proc文件系统,因此,要想使用truss或strace跟踪程序,你必须手工装载proc文件系统:mount -t procfs proc /proc;或者在/etc/fstab中加上一行:

proc                   /proc           procfs  rw              0       0

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

lsof 显示进程打开的文件
lslk 显示进程锁定的文件
strace 调试及跟踪 , 对进程有 strace /truss 等
od 输出文件的内容


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/35489/viewspace-84293/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/35489/viewspace-84293/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用truss、strace或ltrace诊断软件问题 的相关文章

  • for循环计算1-100之间的奇数和偶数的和

    for循环计算1 100之间的奇数和偶数的和 public class ForDemo02 public static void main String args 计算1 100之间的奇数和偶数的和 int oddSun 0 int eve
  • 使用Java的反射和字节码操作实现动态代码生成

    使用Java的反射和字节码操作可以实现动态代码生成 下面是一些步骤和示例代码 1 获取类对象 使用 Class forName 方法或直接使用类名获取类对象 java Class
  • openGL之API学习(一八一)glTexGen

    产生纹理坐标 opengl es无此函数 启用后 根据与该坐标关联的生成函数计算指定的纹理坐标 禁用时 后续顶点从当前纹理坐标集中获取指定的纹理坐标 void glTexGeni GLenum coord GLenum pname GLin
  • C/C++ 获取当前时间(最全方法)

    文章目录 一 获取当前时间 1 使用C语言标准库 2 使用VS提供的ATL模板库 3 使用Win API 二 代码解析 1 time函数 2 localtime函数 3 tm结构体 4 localtime s函数 5 CTime类 6 Ge
  • Redis基本了解

    Redis 基于内存进 存储 持 key value 的存储形式 底层是 C 语 编写的 基于 key value 形式的数据字典 结构 常简单 没有数据表的概念 直接 键值对的形式完成数据的管理 Redis 持 5 种数据类型 字符串 列
  • RecyclerView详解 —— 自定义分割线

    RecyclerView作为ListView和GridView的升级版 Google并没有提供默认的分割线实现 不得不说这是一大遗憾 不过Google为我们提供了一个与之相关的抽象类 public static abstract class
  • 使用Element-Ui的el-select组件无法选中回显的问题

    最近在实习开发中使用了Element Ui的select组件 在选择上级科目下拉后出现了下拉无法回显的情况 但是在科目名称一填内容 上级科目马上就回显了的情况 经过排查也并不是下拉框绑定的值有问题 最后是使用了Vue 官方提供了 vm fo
  • 基于SSM+JSP的高校信息资源共享平台管理系统

    项目背景 21世纪的今天 随着社会的不断发展与进步 人们对于信息科学化的认识 已由低层次向高层次发展 由原来的感性认识向理性认识提高 管理工作的重要性已逐渐被人们所认识 科学化的管理 使信息存储达到准确 快速 完善 并能提高工作管理效率 促
  • Git的git fetch, git merge和git pull, git rebase操作

    Git push merge pull fetch rebase各自在什么场景下使用 基本上顺序是这样的 你修改好了代码 准备要提交到远程仓库 但是此时有可能其他人已经在此分支上已经进行了修改 那么该如何操作呢 这里我们就使用之前模拟多用户
  • 解决 Maven 本地仓库有jar包,还是要到远程仓库去取的问题

    删除maven本地仓库jar包目录下的 lastUpdated 和 repositories 文件 即可解决 使用cmd命令批量清除 cd d cd d maven local repository 首先要进入本地仓库目录 for r i
  • osg传递数组到shader,(以qedl为例)

    一 对float类型的数组 osg ref ptrosg FloatArray m dampingPixelDist 赋值 void ccBilateralFilter updateDampingTable m dampingPixelDi
  • python提示错误TypeError: write() argument must be str, not bytes

    还是在学习 Machine Learning in Action 中决策树一章中 在学习决策树存储过程中先是提示错误TypeError write argument must be str not bytes 看错误信息是说write 函数
  • halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划

    halcon与c 联合编程实现相机控制 图像平移缩放 日志记录 缺陷检测 路径规划 前言 本人近期在工作中遇到需要对某场景下利用海康相机进行图像缺陷检测与对应路径规划 通过对海康相机示例代码进行吸收与借鉴 最终实现了对海康相机的控制 并增加
  • 【c语言】新手学习了switch后的思考总结

    今天初学switch 有了一下四方面的思考 其一 switch是一种语句 这是否意味它需要在某函数内使用 由于初学我的表达不一定准确 即不能独立出来 其二 switch的定位为在多分支的情况下的一种优于 ifelse 的语句 但它的优点在哪
  • css三列布局--两边固定中间自适应和中间固定两边自适应

    三列布局 本篇讲三列布局 面试常考题 自己总结的 如有什么问题 欢迎指出 我会用红色标注出主要作用部分 都是最精简的写法 没有多余的修饰 布局方式一 两边固定中间自适应 1 flex布局 思路 将父元素box设为display flex 可
  • 如果只能推荐3本关于python的书,你会推荐哪3本?

    如果只能推荐3本Python书的话 我推荐这3本 第一本 Python编程快速上手 让繁琐工作自动化 第2版 豆瓣评分8 9 本书是一本面向初学者的Python编程实用指南 本书不仅介绍了Python语言的基础知识 而且通过案例实践教读者如
  • 【QT】Halcon与VS的联合编程2

    1 Halcon代码的导出 导出为C 语言 进行机器视觉应用 在halcon界面的菜单栏项上选择 文件 导出 界面如下 导出之后 在上述导出文件的路径下 你就可以看到程序了 此时这个程序就和halcon没有关系了 就是独立的cpp文件了 2
  • Web3社交基础设施SBT

    今年年初 V神发表了一篇文章并提出soulbound token SBT 概念 5月份 又联合撰写了一篇 去中心化社会 找寻 Web3 的灵魂 让 去中心化社会 和 SBT 概念在大熊市又爆火一波 SBT到底是什么 有什么价值 在概念到应用
  • windows批处理命令总结(超详细滴)

    总结自 https baike baidu com item E6 89 B9 E5 A4 84 E7 90 86 1448600 fr aladdin 文件夹管理 cd 显示当前目录名或改变当前目录 md 创建目录 rd 删除一个目录 d
  • 成功解决Win10连接上wifi但是却显示“无Internet,安全”

    成功解决Win10连接上wifi但是却显示 无Internet 安全 目录 解决问题 解决方法 解决问题 解决Win10连接上wifi但是却显示 无Internet 安全 解决方法 先将wlan先禁用 然后重新启用wlan即可

随机推荐

  • 文心一言和讯飞星火全面对比测试:(五)编程能力

    相关文章 实战 用ChatGPT处理word表格数据 直接采用ChatGPt和利用ChatGPT编写python脚本两种方法 文心一言 vs ChatGPT 结果没有你想向中的那么不堪 文心一言和讯飞星火全面对比测试 一 语言理解能力 文心
  • hbase中的HFile文件格式详解

    1 HFile详解 HFile文件分为以下六大部分 序号 名称 描述 1 数据块 由多个block 块 组成 每个块的格式为 块头 key长 value长 key value 2 元数据块 元数据是key value类型的值 但元数据快只保
  • linux静态链接库与动态链接库的区别及动态库的创建(转)

    linux静态链接库与动态链接库的区别及动态库的创建 转 一 引言 通常情况下 对函数库的链接是放在编译时期 compile time 完成的 所有相关的对象 文件 object file 与牵涉到的函数库 library 被链接合成一个可
  • 算法:位运算

    求整数n的二进制表示中第k位数字是几 最右边那位为第0位 往左依次为第一位 第二位 1 把第k位移到第0位 n gt gt k 2 看一下第0位是几 x 1 include
  • 华为荣耀长按出现第三方信息及服务器,华为荣耀6手机常见问题要领.pdf

    华为荣耀6 手机常见问题 问题 如何升级手机 为防止手机内存中的用户数据 如 联系人 信息 通话记录等 在升级 时被删除 建议升级前备份手机数据 l 在线升级 在线升级前 请连接移动网络或 WLAN 进入 设置 界面 点击 手机升级 gt
  • 有几万块钱做什么生意合适?小本生意介绍

    有很多小伙伴不想上班 想自己出来做生意创业 但是手头只有几万块钱不知道做什么生意合适 那么接下来 我们就来给大家讲解一下这方面的内容 1 开快递代收点 虽然城市里面的快递代收点比较普遍 还有一些智能化的快递投递设备 但是在农村这样的东西很少
  • 如何通过 Libra 测试网络完成一笔转账?

    6 月 18 日 Facebook 宣布 计划于 2020 年发布名为 Libra 的数字货币 目前 Facebook 已经与包括 Visa MasterCard Uber Paypal eBay 等 27 家公司联合建立了协会 用于管理
  • 麒麟V10 X86_64二进制安装minio单机最新版本

    查看系统版本 root lightest minio uname a Linux lightest 4 19 90 25 2 v2101 gfb01 ky10 x86 64 1 SMP Fri Jun 18 12 31 35 CST 202
  • 【华为OD机试真题2023B卷 JAVA&JS】报文重排序

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 报文重排序 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 对报文进行重传和重排序是常用的可靠性机制 重传缓冲区内有一定数量的子报文 每个子报文在原始报文中的顺序已知
  • 电脑提示缺少d3dx9_43.dll的问题及5个解决方法

    大家好 今天 我将和大家分享一个电脑提示缺少d3dx9 43 dll的问题及其解决方法 这个问题可能会影响到我们在使用电脑时的一些功能 所以掌握这个解决方法对我们来说是非常有帮助的 首先 我们来了解一下什么是d3dx9 43 dll d3d
  • tensorflow提示:No module named ''tensorflow.python.eager".

    主要是tensorflow和keras的版本不对应的问题 import keras的时候 提示 No module named tensorflow python eager 明明昨天用还没问题 而且网上竟然没有解决方案 就考虑了一下tf和
  • win11下安装golang

    背靠国外各大金主的go语言 在各种推动下 可谓是新的弄潮儿 但国内虽然各种推销 但从安装到开发再到维护 资料都少之又少 可能被垄断了解释权吧 因此下面的也只是一个记录而已 是一次仅限于本人本机本阶段的成功尝试 一 win11下golang安
  • 一些LitJson的方法

    Json转为HashTable Hashtable JsonToHashTable JsonData data Hashtable hashtable new Hashtable string keys GetJsonKeys data f
  • Vue - el-upload 组件在 on-success 文件上传成功的钩子中传递更多参数

    ElementUI Upload 上传官网 https element eleme cn zh CN component upload 在ElementUI官网中upload组件的on success的钩子中 只能传递 response f
  • 蓝桥杯-2013年B组真题

    蓝桥杯 2013年B组真题 蓝桥杯 2013年B组真题 参考 https blog csdn net qq 44391957 article details 90646760 A 高斯日志 题目标题 高斯日记 大数学家高斯有个好习惯 无论如
  • Jeff Atwood质疑iPhone的单键设计

    我喜欢使用iPhone 但我对它的一个设计不敢苟同 苹果始终坚持 设备的正面永远只能有一个按键 我还买了一个Kindle Fire 它更离谱 一个按键都没有 我完全赞成 任何小器具的正面都应该在明显的位置上至少有一个 耶稣把手 一样的按键
  • Tomcat出现404的解决方法[类型 状态报告 消息 请求的资源[/]不可用 描述 源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源]

    解决idea的web项目tomcat启动后无法加载index jsp文件 404 问题 使用servlet是正常的 可以用以下解决方式 打开项目设置Project Structure 点击进入Project Settings下的Facets
  • AI智能图像识别的工作原理及行业应用

    AI智能图像识别 人工智能 AI 的一部分 是当今一个正在蓄势待发的人工智能大趋势 富维图像也正在从事图像识别技术研发和应用 数据显示 人工智能图像识别市场规模已达到近390亿美元 所以AI智能图像识别技术已经存在我们的工作以及生活环境当中
  • paxos算法java实现_基于python的Paxos算法实现

    理解一个算法最快 最深刻的做法 我觉着可能是自己手动实现 虽然项目中不用自己实现 有已经封装好的算法库 供我们调用 我觉着还是有必要自己亲自实践一下 这里首先说明一下 python这种动态语言 对不熟悉的人可能看着比较别扭 不像java那样
  • 使用truss、strace或ltrace诊断软件问题

    进程无法启动 软件运行速度突然变慢 程序的 Segment Fault 等等都是让每个Unix系统用户头痛的问题 本文通过三个实际案例演示如何使用truss strace和ltrace这三个常用的调试工具来快速诊断软件的 疑难杂症 trus