目录
本文章内容主要参考strace的手册页。
strace是一个可用于诊断、调试的Linux用户空间跟踪器。主要用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等,其底层使用内核的ptrace特性来实现。在日常运维中,strace作为一种动态跟踪工具,可以帮助我们高效地定位进程和服务故障。
文章中列出的strace用法及其选项的说明基于strace版本4.24。
一、用法
strace用法如下:
strace [-CdffhiqrtttTvVwxxy] [-I n] [-e expr]...
[-a column] [-o file] [-s strsize] [-P path]...
-p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
或者:
strace -c[dfw] [-I n] [-e expr]... [-O overhead] [-S sortby]
-p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
二、参数选项类型详解
1、日志格式输出控制类
-a column
将系统调用结果按指定的长度输出,默认40
-i
输出系统调用的指令(入口)指针
-k
获取每个系统调用之间的堆栈轨迹信息
-o file
将strace的输出写入文件file而不是stderr
-q
不输出关于附加、脱离等消息。当输出被重定向到文件并且命令直接运行而不是附加时,会自动触发
-r
打印每一个系统调用相对于上一个调用的相对时间戳
-s strsize
限制输出字符串的长度为STRSIZE个字符,默认为32,如果设置过小,一些长字符串将不会输出。文件名不受影响
-t
输出信息加上当前时间信息
-tt
输出信息加上带微秒的当前时间信息
-T
显示每一个系统调用的耗时
-x
以十六进制输出非标准字符串
-xx
以十六进制输出所有字符串
-X format
设置指定常量和标志的输出格式
-y
打印与文件描述符参数相关的路径
-yy
打印与套接字文件描述符相关的协议特定信息
2、统计类
输出跟踪系统调用时的相关统计信息。
-c
统计每一个系统调用所执行的时间,次数和错误数等,并打印摘要信息,如果与-f 一起使用,则仅保留所有被跟踪进程的相加的总量
-C
与-c类似,不过在进程运行时也打印常规输出
-O overhead
当使用-c选项统计系统调用时间时,设置跟踪系统调用的开销时间上限为overhead微秒
-S sortby
对-c选项的输出按某种排序方式(时间、调用次数、名称等)来排序,默认按时间排序
-w
总结每个系统调用开始和结束的时间差。默认是汇总的系统时间
3、筛选过滤类
用于筛选过滤出想要跟踪的指定的系统调用。主要有两个参数选项:
(1).-e expr
expr表达式的格式为: option=[!]all or option=[!]val1[,val2]... !表示取反,部分shell中!有特殊含义,需要用的时候可以使用\转义。option有如下几种:
<1>.-e trace=set
跟踪指定的某类系统调用,不知道要跟踪哪些系统调用时,可以使用-c选项查看一下程序运行时都进行了哪些系统调用。默认跟踪所有系统调用。使用trace表达式跟踪时,可指定的类型如下:
-e trace=/regex
只跟踪那些匹配指定正则表达式的系统调用
-e trace=%file
跟踪所有涉及文件访问的系统调用,其效果跟-e trace=open,stat,chmod,unlink,...一样。对于查看进程运行时调用了哪些文件很有用。
-e trace=%process
跟踪所有涉及进程管理的系统调用,比如fork/exec/exit_group,这对于查看进程的 fork、wait 和 exec 步骤很有用。
-e trace=%network
跟踪所有涉及网络通信的系统调用,比如socket/sendto/connect
-e trace=%signal
跟踪所有涉及信号发送和处理的系统调用,比如kill/sigaction
-e trace=%desc
跟踪与文件描述符相关的系统调用,比如write/read/select/epoll等
-e trace=%ipc
跟踪与进程通讯有关的系统调用,比如shmget等
-e trace=%memory
跟踪所有涉及内存映射的系统调用
-e trace=%stat
跟踪 stat 系统调用的另一种写法
-e trace=%lstat
跟踪 lstat 系统调用的另一种写法
-e trace=%fstat
跟踪 fstat 系统调用的另一种写法
-e trace=%%stat
跟踪用于请求文件状态的系统调用(stat、lstat、fstat、fstatat、statx)
-e trace=%statfs
跟踪 statfs、statfs64、statvfs、osf_statfs 和 osf_statfs64 系统调用。使用-e trace=/^(.*_)?statv?fs正则表达式可以达到同样的效果
-e trace=%fstatfs
跟踪 fstatfs、fstatfs64、fstatvfs、osf_fstatfs 和 osf_fstatfs64 系统调用。使用-e trace=/fstatv?fs可以达到同样的效果
-e trace=%%statfs
跟踪与文件系统统计信息相关的系统调用(类似 statfs、类似 fstatfs 和 ustat)。使用-e trace=/statv?fs|fsstat|ustat正则表达式可以达到同样的效果
-e trace=%pure
跟踪总是成功且不带参数的系统调用。如:getpagesize(2) )、getpgrp(2)、getpid(2)、getppid(2)系统调用
注意:以上列出的从file到memory的不带%的形式已弃用,建议使用时都带上%
<2>.-e abbrev=set
简单打印指定的大型结构体的每个成员的输出信息,默认值为 abbrev=all,如果abbrev=none,则效果同-v选项。
<3>.-e verbose=set
为指定的系统调用集解析引用结构,默认verbose=all
<4>.-e raw=set
将指定的系统调用的参数以十六进制显示
<5>.-e signal=set
跟踪指定的系统信号子集.默认为all.如 signal=!SIGIO(或者signal=!io),则不跟踪SIGIO信号
<6>.-e read=set
对指定集合中列出的文件描述符所读取的所有数据执行完整的十六进制和 ASCII 转储。例如,要查看文件描述符 3 和 5 上的所有输入活动,请使用 -e read=3,5。需要注意,这与选项-e trace=read跟踪的read(2)系统调用无关。
<7>.-e write=set
对写入指定集合中列出的文件描述符的所有数据执行完整的十六进制和 ASCII 转储。例如,要查看文件描述符 3 和 5 上的所有输出活动,请使用 -e write=3,5。需要注意,这与选项 -e trace=write 跟踪的 write(2) 系统调用无关。
<8>.-e inject=set[:error=errno|:retval=value][:signal=sig][:syscall=syscall][:delay_enter=usecs][:delay_exit=usecs][:when=expr]
系统调用注入,对指定的系统调用集的系统调用进行修改。必须至少指定 error、retval、signal、delay_enter 或 delay_exit 选项之一。其中error 和 retval 是互斥的。
:error=errno 选项
会在系统调用的调用中注入错误,系统调用编号被替换为 -1,这对应于无效的系统调用(除非使用 :syscall= option选项指定某个系统调用),并且错误代码限定为使用符号 errno 值比如ENOSYS或者1..4095 范围内的数值。
:retval=value
选项,则执行成功注入:系统调用号被替换为 -1,不过会向被调用者返回一个虚假的成功值
:signal=sig
选项指定为符号值(如 SIGSEGV)或 1..SIGRTMAX 范围内的任意数字,则在进入指定类型的每个系统调用时都将传递该信号
:delay_enter=usecs 或 :delay_exit=usecs
选项,则执行延迟注入:tracee在进入或退出系统调用时至少延迟 usecs微秒
如果只指定:signal=sig 选项而没有指定:error=errno, :retval=value或:delay_{enter,exit}=usecs选项,则仅信号 sig 会被传递,而不会有错误系统调用和延迟注入。同样的,不带:delay_enter=usecs,:delay_exit=usecs 或 :signal=sig选项的:error=errno 或者:retval=value选项将仅注入错误而不传递信号或者注入延迟。其他情况类似。
如果:error=errno/:retval=value 和 :signal=sig 选项都指定,则注入错误或成功并传递信号
:syscall=syscall 选项,则注入没有副作用的相应系统调用而不是 -1。目前,仅用于指定为"纯"(参见-e trace=%pure 相关内容)的系统调用。
:when=expr
除非指定了 :when=expr,否则将对筛选集里的每个系统调用的每次调用都进行注入。
表达式的格式可选择如下任一种:
1).first
对于筛选集里的每个系统调用,仅对第first个系统调用执行注入 。
2).first+
对于筛选集里的每个系统调用,对第first个系统调用及所有后续调用进行注入。
3).first+step
对于筛选集里的每个系统调用,对第first个系统调用及后续每step个系统调用进行注入。
first 和 step 的数值有效范围是 1..65535。
举例来说,在chdir系统调用第3次及其后续调用中注入错误ENOENT,可表示为:-e inject=chdir:error=ENOENT:when=3+。
注意:一个注入表达式只能包含一个 error= 或 retval= 选项,并且只能包含一个 signal= 选项。如果一个注入表达式包含多个 when= 选项,则最后一个有效。
系统调用注入选项可以与其他系统调用过滤选项结合使用。如: -P /dev/urandom -e inject=file:error=ENOENT。
<9>.-e fault=set[:error=errno][:when=expr] 为指定的系统调用集执行系统调用的错误注入,等效于更通用的-e inject= expression,其中errno选项的默认值为ENOSYS
<10>.-e kvm=vcpu 打印kvm vcpu的退出原因。需要 Linux 内核 4.16.0 或更高版本。
(2).-P path
仅跟踪指定路径的系统调用。多个 -P 选项可用于指定多个路径。
4、跟踪方式类
设置跟踪进程的方式,相关选项如下:
-b syscall
如果跟踪到指定的系统调用,则从被跟踪的进程中分离。目前,仅支持execve(2)系统调用。如果您想跟踪多线程进程并因此需要-f选项,又不想跟踪其(可能非常复杂的)子进程,则此选项很有用
-D
将跟踪进程作为独立的孙子进程运行,而不是作为父进程运行
-f
跟踪目标进程,以及目标进程创建的所有子进程
-ff
跟踪目标进程,以及目标进程创建的所有子进程并单独输出到各自的文件中
另外还有一个-I选项:
-I interruptible 设置strace是否可以被信号中断(比如按 CTRL-C),有如下4种设置:
1:
信号将正常执行
2:
当解码系统调用时会阻止致命信号(默认值)
3:
总是阻止致命信号(当-o FILE PROG时,此时为默认值)
4:
总是阻止致命信号和SIGTSTP(暂停)信号(此时strace -o FILE PROG在按CTRL-Z时不会停止)
5、命令启动设置类
在使用strace跟踪程序命令时,可以对其进行一定的设置,让程序运行在我们希望的条件下,并对其跟踪。
-E
在将 var 传递给命令之前,从继承的环境变量列表中删除 var
-E var=val
在其环境变量列表中使用 var=val 运行命令
-p pid
根据PID跟踪正在运行的某个进程的执行情况,按ctrl + C 结束跟踪,被跟踪进程不会受影响。除命令外,使用多个 -p 选项还附加到许多进程。支持语法:-p "`pidof PROG`"。
-u username
使用用户 ID、组 ID 和用户名的补充组来运行命令。此选项仅在以 root 身份运行时有用并且让setuid 和 setgid二进制文件正确执行。如果不启用此选项,setuid 和 setgid 程序将在没有有效权限的情况下执行
6、其他类型
一些辅助的选项。
其他:
-d
在stderr上输出strace 本身的一些调试信息
-v
开启详细模式,会打印环境、统计、termios 等调用的非缩写形式
-h
显示帮助信息
-V
显示版本信息