0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

strace是什么 怎样使用它

Linux爱好者 来源:Linux爱好者 作者:有心故我在 2020-11-17 18:16 次阅读

什么是strace?

strace是一个非常简单的工具,它可以跟踪系统调用的执行。最简单的方式,它可以从头到尾跟踪binary的执行,然后以一行文本输出系统调用的名字,参数和返回值。

其实它可以做的更多:

可以对特定的系统调用或者几组系统调用进行过滤

可以通过统计特定系统调用的调用次数、耗费的时间、成功和失败的次数来配置(profile)系统调用的使用 I

跟踪发送给进程的信号

可以通过pid附着(attach)到任何运行的进程

如果你使用的是其它Unix系统,它类似于"truss"。其它更复杂的是Sun的Dtrace.

怎么使用它

1) 找出程序在startup的时候读取的哪个config文件?

有没有尝过解决为什么某些程序不读去你认为它应该读取的config文件的问题?

$ strace php 2>&1 | grep php.ini open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/local/lib/php.ini", O_RDONLY) = 4 lstat64("/usr/local/lib/php.ini", {st_mode=S_IFLNK|0777, st_size=27, ...}) = 0 readlink("/usr/local/lib/php.ini", "/usr/local/Zend/etc/php.ini", 4096) = 27 lstat64("/usr/local/Zend/etc/php.ini", {st_mode=S_IFREG|0664, st_size=40971, ...}) = 0

可以看出这个版本的PHP从/usr/local/lib/php.init读取config文件(但是先尝试/usr/locl/bin)

如果只关心特定的系统调用,有更精致的方法

$ strace -e open php 2>&1 | grep php.ini open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/local/lib/php.ini", O_RDONLY) = 4

相同的方法适用于很多其它类似的问题。比如说,安装了不同版本的library,不确定实际上加载了哪一个版本。

-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...

options: trace, abbrev, verbose, raw, signal, read, write

2) 为什么这个程序没有打开我的文件?

是否曾经碰到过一个程序拒绝读取它没有权限的文件,但是你发誓原因是它没有真正找到那个文件?对程序跟踪open,access调用,注意失败的情况

$ strace -e open,access 2>&1 | grep your-filename

3) 某个进程现在在做什么?

某个进程突然占用了很多CPU? 或者某个进程看起来像hanging了?

找到对应的pid,然后

hang:

悬挂,挂起的意思

就是一个进程被暂时停止执行.

root@dev:~# strace -p 15427 Process 15427 attached - interrupt to quit futex(0x402f4900, FUTEX_WAIT, 2, NULL Process15427detached

嗯,这个例子里面,它在调用futex()的时候挂起了。

"strace -p"非常有用,它减少了很多猜测工作,也不需要重新启动应用。

-p pid -- trace process with process id PID, may be repeated

4) 是谁偷走了时间?

你可以重新编译app,打开profiling,以获取精确的信息。但是通常利用strace附着(attach)一个进程以快速地看一下当前时间花费在哪里非常有用。可以看下是否90%的CPU用在真正的工作,或者用在其它方面了。

root@dev:~# strace -c -p 11084 Process 11084 attached - interrupt to quit Process 11084 detached % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 94.59 0.001014 48 21 select 2.89 0.000031 1 21 getppid 2.52 0.000027 1 21 time ------ ----------- ----------- --------- --------- ---------------- 100.00 0.001072 63 total root@dev:~#

-c -- count time, calls, and errors for each syscall and report summary

-C -- like -c but also print regular output

在执行strace -c -p命令以后,等到你关注的时间到了后,按ctrl-c退出,strace会列出如上的profiling数据。

在这个例子中,程序花了绝大部分时间在等待select()。它在每一个slect()调用这件调用getpid()和time(),这是一种典型的事件循环。

你也可以运行"start to finish",这里是"ls"

root@dev:~# strace -c >/dev/null ls % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 23.62 0.000205 103 2 getdents64 18.78 0.000163 15 11 1 open 15.09 0.000131 19 7 read 12.79 0.000111 7 16 old_mmap 7.03 0.000061 6 11 close 4.84 0.000042 11 4 munmap 4.84 0.000042 11 4 mmap2 4.03 0.000035 6 6 6 access 3.80 0.000033 3 11 fstat64 1.38 0.000012 3 4 brk 0.92 0.000008 3 3 3 ioctl 0.69 0.000006 6 1 uname 0.58 0.000005 5 1 set_thread_area 0.35 0.000003 3 1 write 0.35 0.000003 3 1 rt_sigaction 0.35 0.000003 3 1 fcntl64 0.23 0.000002 2 1 getrlimit 0.23 0.000002 2 1 set_tid_address 0.12 0.000001 1 1 rt_sigprocmask ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000868 87 10 total

正如你的预期,它耗费了大部分时间在两次调用来读取目录条目上(因为运行于一个小的目录上,所有只有两次)

5) 为什么 无法连接到服务器?

调试进程无法连接到远端服务器有时候是件非常头痛的事。DNS会失败,connect会挂起,server有可能返回一些意料之外的数据。

可以使用tcpdump来分析这些情况,它是一个非常棒的工作。但是有时候你strace可以给你更简单,耿直借的角度,因为strace只返回你的进程相关的系统调用产生的数据。

如果你要从100个连接到统一个数据服务器的运行进程里面找出一个连接所做的事情,用strace就比tcpdump简单得多。

下面是跟踪"nc"连接到www.news.com 80端口的例子

$ strace -e poll,select,connect,recvfrom,sendto nc www.news.com 80 sendto(3, "242613255373NH", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, 28) = 0 poll([{fd=3, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1 sendto(3, "213321113www4news3com341", 30, MSG_NOSIGNAL, NULL, 0) = 30 poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1 recvfrom(3, "2133212012001113www4news3com341300f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, [16]) = 153 connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, 28) = 0 poll([{fd=3, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1 sendto(3, "k374113www4news3com11", 30, MSG_NOSIGNAL, NULL, 0) = 30 poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1 recvfrom(3, "k374201200123www4news3com11300f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, [16]) = 106 connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, 28) = 0 poll([{fd=3, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1 sendto(3, "\2113www4news3com11", 30, MSG_NOSIGNAL, NULL, 0) = 30 poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1 recvfrom(3, "\2201200123www4news3com11300f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, [16]) = 106 connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("216.239.122.102")}, 16) = -1 EINPROGRESS (Operation now in progress) select(4, NULL, [3], NULL, NULL) = 1 (out [3])

发生了什么?

注意到尝试连接/var/run/nscd/socket?这意味着nc首先尝试连接NSCD--the Name Service Cache Daemon--它通常用来基于NIS,YP,LDAP或者类似的目录协议提供域名查询。在这里它失败了。

然后它连接DNS(DNS是port 53,所以"sin_port=htons(53)")。然后它调用了"sendto()“,发送包含www.news.com的DNS 包。


然后读回响应。不知为何,它尝试了三次,最后一次有细微的却别,我猜是它www.news.com十一个CNAME(别名),多次请求可能是nc故意的。

最后,它发起一个connect()请求到得到的IP地址,注意到返回值是EINPROGRESS。这意味这connect是非阻塞的,nc希望继续处理,然后它调用slect(),连接建立后,select返回成功。

添加"read","write"到过滤系统调用列表中,连接时输入一个字串,可能会得到如下

Notice the connection attempts to /var/run/nscd/socket? They mean nc first tries to connect to NSCD - the Name Service Cache Daemon - which is usually used in setups that rely on NIS, YP, LDAP or similar directory protocols for name lookups. In this case the connects fails.

It then moves on to DNS (DNS is port 53, hence the "sin_port=htons(53)" in the following connect. You can see it then does a "sendto()" call, sending a DNS packet that contains www.news.com. It then reads back a packet. For whatever reason it tries three times, the last with a slightly different request. My best guess why in this case is that www.news.com is a CNAME (an "alias"), and the multiple requests may just be an artifact of how nc deals with that.

Then in the end, it finally issues a connect() to the IP it found. Notice it returns EINPROGRESS. That means the connect was non-blocking - nc wants to go on processing. It then calls select(), which succeeds when the connection was successful.

Try adding "read" and "write" to the list of syscalls given to strace and enter a string when connected, and you'll get something like this:

read(0, "test ", 1024) = 5 write(3, "test ", 5) = 5 poll([{fd=3, events=POLLIN, revents=POLLIN}, {fd=0, events=POLLIN}], 2, -1) = 1 read(3, "

这表示从标准输入读入"test"+换行符,并写到网络连接中,然后调用poll等待响应,读取响应,写回标准输出。

一切看起来都正常工作。

早些年,如果你知道有个 strace 命令,就很牛了,而现在大家基本都知道 strace 了,如果你遇到性能问题求助别人,十有八九会建议你用 strace 挂上去看看,不过当你挂上去了,看着满屏翻滚的字符,却十有八九看不出个所以然。

本文通过一个简单的案例,向你展示一下在用 strace 诊断问题时的一些套路。

如下真实案例,如有雷同,实属必然!让我们看一台高负载服务器的 top 结果:

技巧:运行 top 时,按「1」打开 CPU 列表,按「shift+p」以 CPU 排序。

在本例中大家很容易发现 CPU 主要是被若干个 PHP 进程占用了,同时 PHP 进程占用的比较多的内存,不过系统内存尚有结余,SWAP 也不严重,这并不是问题主因。

不过在 CPU 列表中能看到 CPU 主要消耗在内核态「sy」,而不是用户态「us」,和我们的经验不符。Linux 操作系统有很多用来跟踪程序行为的工具,内核态的函数调用跟踪用「strace」,用户态的函数调用跟踪用「ltrace」,所以这里我们应该用「strace」:

shell> strace -p

不过如果直接用 strace 跟踪某个进程的话,那么等待你的往往是满屏翻滚的字符,想从这里看出问题的症结并不是一件容易的事情,好在 strace 可以按操作汇总时间:

shell> strace -cp

通过「c」选项用来汇总各个操作的总耗时,运行后的结果大概如下图所示:

很明显,我们能看到 CPU 主要被 clone 操作消耗了,还可以单独跟踪一下 clone:

shell> strace -T -e clone -p

通过「T」选项可以获取操作实际消耗的时间,通过「e」选项可以跟踪某个操作:

很明显,一个 clone 操作需要几百毫秒,至于 clone 的含义,参考 man 文档:

clone() creates a new process, in a manner similar to fork(2). It is actually a library function layered on top of the underlying clone() system call, hereinafter referred to as sys_clone. A description of sys_clone is given towards the end of this page.

Unlike fork(2), these calls allow the child process to share parts of its execution context with the calling process, such as the memory space, the table of file descriptors, and the table of signal handlers. (Note that on this manual page, “calling process” normally corresponds to “parent process”. But see the description of CLONE_PARENT below.)

简单来说,就是创建一个新进程。那么在 PHP 里什么时候会出现此类系统调用呢?查询业务代码看到了 exec 函数,通过如下命令验证它确实会导致 clone 系统调用:

shell> strace -eclone php -r 'exec("ls");

最后再考大家一个题:如果我们用 strace 跟踪一个进程,输出结果很少,是不是说明进程很空闲?其实试试 ltrace,可能会发现别有洞天。记住有内核态和用户态之分。

strace -f -e trace=read,write -p 17151 -o log #跟踪进程17151及子进程中read和write系统调用,输出到log文件.

-e expr

指定一个表达式,用来控制如何跟踪.格式如下:

[qualifier=][!]value1[,value2]...

qualifier 只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.

value是用来限定的符号或数字.

默认的 qualifier是 trace.

感叹号是否定符号.

例如:

-eopen等价于 -e trace=open,表示只跟踪open调用.

而-etrace!=open表示跟踪除了open以外的其他调用.

有两个特殊的符号 all 和 none.

注意有些shell使用!来执行历史记录里的命令,所以要使用.

-e trace=

只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.

-e trace=file

只跟踪有关文件操作的系统调用.

-e trace=process

只跟踪有关进程控制的系统调用.

-e trace=network

跟踪与网络有关的所有系统调用.

-e strace=signal

跟踪所有与系统信号有关的 系统调用

-e trace=ipc

跟踪所有与进程通讯有关的系统调用

-e abbrev=

设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.

-e raw=

将指 定的系统调用的参数以十六进制显示.

-e signal=

指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.

-e read=

输出从指定文件中读出 的数据.例如:

-e read=,

-e write=

通用的完整用法:

strace -o output.txt -T -tt -e trace=all -p 28979

上面的含义是 跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。

语法

strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ... [ -ofile ] [-ppid ] ... [ -sstrsize ] [ -uusername ] [ -Evar=val ] ... [ -Evar ]... [ command [ arg ... ] ]

strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg... ] ]

责任编辑:xj

原文标题:Linux 神器 strace 查故障的 5 种简单方法

文章出处:【微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1366

    浏览量

    40236
  • Linux
    +关注

    关注

    87

    文章

    11232

    浏览量

    208960
  • strace命令
    +关注

    关注

    0

    文章

    2

    浏览量

    6444

原文标题:Linux 神器 strace 查故障的 5 种简单方法

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    怎样选择合适的MOSFET

    怎样选择合适的MOSFET
    的头像 发表于 10-01 08:01 212次阅读
    <b class='flag-5'>怎样</b>选择合适的MOSFET

    用PGA309芯片做一款压力变送器的信号调节电路,是否可以用它连接自己设计的电路板并校准呢?

    因为打算用PGA309芯片做一款压力变送器的信号调节电路,买了PGA309EVM, 请问是否可以用它连接自己设计的电路板并校准呢? 如果可以,该怎么连接?
    发表于 09-02 06:50

    贴片电感电流超过额定电流会怎样

    电子发烧友网站提供《贴片电感电流超过额定电流会怎样.docx》资料免费下载
    发表于 07-30 10:37 2次下载

    stm32使用workbench只生成了一些.h和.c文件,然后该如何使用它们?

    使用workbench只生成了一些.h和.c文件,然后该如何使用它们?还需要手动在MDK中建立工程添加标准库再把这些文件加进去么?哪位有相关开发经验,请赐教!
    发表于 05-15 07:29

    【鸿蒙】OpenHarmony使用strace

    简介 Strace 是一个强大的进程行为跟踪工具,当怀疑某个进程运行异常的时候,比如死锁,CPU 高或者莫名卡顿等,可以使用 strace 查看该进程发起的系统调用和接收到的信号,从而确定问题所在
    的头像 发表于 03-01 09:41 767次阅读
    【鸿蒙】OpenHarmony使用<b class='flag-5'>strace</b>

    提升机轴头磨损怎样修复

    电子发烧友网站提供《提升机轴头磨损怎样修复.docx》资料免费下载
    发表于 02-27 15:56 0次下载

    烘缸轴磨损怎样

    电子发烧友网站提供《烘缸轴磨损怎样修.docx》资料免费下载
    发表于 02-23 10:00 0次下载

    稳压管起稳压作用是利用它的什么特性

    稳压管(Voltage Regulator),也称为稳压二极管、稳压二极管、稳压二极管、硅稳压二极管等,是一种能够稳定输出电压的电子元件。 稳压管起稳压作用是利用它的电流-电压特性。下面是一个深入
    的头像 发表于 02-22 10:09 2675次阅读

    以太网交换机有何特点?用它怎样组成虚拟局域网

    以太网交换机有何特点?用它怎样组成虚拟局域网  以太网交换机是一种用于组建局域网(LAN)的关键设备,它有许多特点和功能。为了让文章更详尽、详实、细致,我将依次介绍以太网交换机的起源、工作原理、特点
    的头像 发表于 02-20 14:26 4417次阅读

    SPWM调制方式是怎样实现变压功能的?又是怎样实现变频功能的?

    SPWM调制方式是怎样实现变压功能的?又是怎样实现变频功能的? SPWM是一种常见的调制方式,它通过调节脉冲的宽度来控制输出波形的幅度和频率,因此可以实现变压和变频功能。下面将详细介绍SPWM调制
    的头像 发表于 02-06 11:09 1554次阅读

    安装了HighteCide和DAS来连接TriBoard然后使用它,为什么不起作用?

    我试着用 TriBoard TC3X9 TH V2.01 我安装了 HighteCide 和 DAS 来连接 TriBoard 然后使用它。 但是,它不起作用,我看到了这样的窗口。 我
    发表于 01-30 08:28

    图像采集卡到底是什么?为什么要使用它们?

    :图像采集卡到底是什么?它们有什么用?何时以及为什么应该使用它们?为什么要使用图像采集卡?帧或视频采集卡的最初目的是将模拟图片转换为数字信号。由于当今纯数字图像处理技
    的头像 发表于 01-26 16:14 1424次阅读
    图像采集卡到底是什么?为什么要使<b class='flag-5'>用它</b>们?

    怎样设计和验证TRL校准件以及TRL校准的具体过程

    怎样设计和验证TRL 校准件以及TRL 校准的具体过程
    发表于 12-14 09:40 0次下载

    怎样快速生成“无源电感Pcell”?

    怎样快速生成“无源电感Pcell”?
    的头像 发表于 12-06 16:13 800次阅读
    <b class='flag-5'>怎样</b>快速生成“无源电感Pcell”?

    现代设计,需要怎样的 PMIC?

    现代设计,需要怎样的 PMIC?
    的头像 发表于 12-05 17:42 501次阅读
    现代设计,需要<b class='flag-5'>怎样</b>的 PMIC?