Dec
18
strace是很有用的分析,指导和调试工具。当面对那些源码并不可靠的程序时,系统管理员,分析师和故障检测师们会发现strace是非常棒的,因为他们不需要重新编译就可以跟踪了!学生,黑客以及那些喜欢猎奇的人们也会发现,仅仅通过跟踪很普通的程序就可以对了解一个系统和它的系统调用很有帮助。由于系统调用和信号是发生在用户/内核接口上的事件,这也使程序员们感觉到细致地检查这个边界点对于分离bug,健壮性检测和捕捉瞬间状态很有用。
以下内容转自sywang#redflag-linux.com的翻译。
以下内容转自sywang#redflag-linux.com的翻译。
引用
STRACE(1) STRACE(1)
名称
strace - 跟踪系统调用和信号
概要
strace [ -dffhiqrtttTvxx ] [ -a列值 ] [ -e表达式 ] ... [ -o文件名 ] [ -p
进程号 ] ... [ -s字符串长度 ] [ -u用户名 ] [ -E变量=val ] ... [ -E变量 ]
.... [ 命令 [ 参数 ... ] ]
strace -c [ -e表达式 ] ... [ -O总数 ] [ -S排序 ] [ 命令 [ 参数 ... ] ]
描述:
简单地说,strace就是运行一个特定的命令,直到它退出。它截取并记录进程产生
的系统调用和进程接收到的信号。每个系统调用,它的参数及其返回值将打印到标
准错误输出或通过-o选项保存到指定文件。
strace是很有用的分析,指导和调试工具。当面对那些源码并不可靠的程序时,系
统管理员,分析师和故障检测师们会发现strace是非常棒的,因为他们不需要重新
编译就可以跟踪了!学生,黑客以及那些喜欢猎奇的人们也会发现,仅仅通过跟踪
很普通的程序就可以对了解一个系统和它的系统调用很有帮助。由于系统调用和信
号是发生在用户/内核接口上的事件,这也使程序员们感觉到细致地检查这个边界
点对于分离bug,健壮性检测和捕捉瞬间状态很有用。
跟踪信息的每一行都包括系统调用的名称,它的参数跟在后面的()中,还有它的返
回值。例如,跟踪 'cat /dev/null' 这个命令其中有一行是:
open("/dev/null", O_RDONLY|O_LARGEFILE) = 3
而错误 (一般返回值为 -1) 有一个错误号和一个错误字串:
open("/foo/bar", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
信号是作为信号标识和信号字符串打印的。 跟踪并中断‘sleep 666‘时有一段是这
样的:
sigsuspend([]
--- SIGINT (Interrupt) ---
+++ killed by SIGINT +++
参数用带有情绪色彩的符号方式打印出来。
下面这个例子执行了‘‘>>xyzzy’’的重定向脚本:
open("xyzzy", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
在这里,open的3个参数形式通过分解标识符解码为3个按位与的成员并打印为传统
的8进制. 传统的用法和ANSI或POSIX不大一样,不过更倾向于使用后者。有些情况
下,strace的输出比源码可读性更好些。
结构指针会被复用并且其成员同样适当显示出来。所有情况下参数都会以尽可能像
C那样的格式表现。例如:命令‘‘ls -l /dev/null’’的核心部分捕捉为:
lstat("/dev/null", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
请注意‘struct stat’参数是如何被复用的,其成员是如何形象显示的。 另外成员
st_mode被细致地解码成了符号和数值的按位与。还要注意lstat的第一个参数是系
统调用的输入,跌入个则是输出。如果系统调用失败,则输出参数值不变,因此参
数并不是总被复用的。比如,再用‘‘ls -l’’列出一个不存在的文件 '/foo/bar
',会有如下输出:
lstat("/foo/bar", 0xb004) = -1 ENOENT (没有那个文件或目录)
在这种情况下复用是没必要的。
字符指针被复用并且并以C字符串形式显示出来。 字符串中的非打印字符一般用 C
转义符表示,不过仅仅打印第一组 strsize (缺省为32个) 大小字节的字符串;剩
下的用省略号代替。这里有一行‘‘ls -l’’命令输出,是调用getpwuid库读取密码
文件时的情况:
read(3, "root::0:0:System Administrator:/"..., 1024) = 422
除了结构使用()表示,简单的指针和数组则使用[]来表示,其中元素用 ' , ' 隔
开。这里的例子是跟踪‘‘id’’命令的输出:
getgroups(32, [100, 0]) = 2
另外, bit-sets 也使用[]表示,不过组元素只是用空格分开。这里是一个将要执
行外部命令的脚本:
sigprocmask(SIG_BLOCK, [CHLD TTOU], []) = 0
这里的第二个参数是有两个信号的 bit-set 。有时候 bit-set 元素太多,相反其
他非bit-set 元素更有打印价值,此时会表示如下:
sigprocmask(SIG_UNBLOCK, ~[], NULL) = 0
这里第二个参数代表整个bit-set。
选项
-c 为每个系统调用计算时间、调用次数和错误次数,并在程序退出时打印统计报
表。对于Linux来说,这表示的是系统时间 (运行在核心态时占用的CPU时间) ,独
立于时钟时间。如果 -c 和 -f 或 -F (如下)一同使用, 则只保留所有跟踪进程的
总和。
-d 把一些strace自身的调试信息显示到标准错误输出。
-f
跟踪当前进程通过fork系统调用派生的子进程。一旦获得子进程号,它将被跟踪
(通过父进程fork的返回值). 这意味着这种子进程将存在一个不可控期(尤其使用
vfork(2)的情况), 直到父进程再次规划好来完成这个 (v)fork(2) 调用。如果父
进程决定wait(2)一个正被跟踪的子进程,它将一直挂起,直到子进程终止或子进程
收到了使其终止的信号(当前子进程的信号处理情况决定).
-ff
如果同时使用了-o filename参数, 每个子进程调试信息都会记录到各自的
filename.pid 中。它与-c这个选项不兼容,因为 -c 是不保留单独进程记录的。
-F 尝试跟踪vfork. (在SunOS 4.x上, 使用一些动态链接技巧可以实现.)。否则,
即使使用-f参数,vfork也不会跟踪。
-h 打印帮助信息。
-i 在进行系统调用时打印指令指针地址。
-q 忽略attach, detach等信息。如果输出重定向到文件并且命令直接运行而不是
attach的,该选项自动启用。
-r 对每一个系统调用入口打印相对时间戳。这将记录两个连续的系统调用起始时
刻的时间差。
-t 在每一行信息前加入当前时间。
-tt 如果有两个t参数,当前时间将精确到微秒。
-ttt 如果有三个t参数, 当前时间将精确到微秒,并且整数部分将以1970年为基准
的秒数计算.
-T 记录花费在系统调用上的时间。这将记录每个系统调用从开始到结束的时间差。
-v 显示更详细信息。
-V 显示strace的版本号。
-x 打印十六进制格式的所有非ascii码。
-xx 以十六进制格式打印所有字符。
-a 以指定列值对齐打印返回值(缺省为第40列)
-e expr 限定表达式。它修改跟踪的事件以及如何跟踪它们。 表达式的格式为:
[限定词=][!]value1[,value2]...
限定词可以为 trace, abbrev, verbose, raw, signal, read 或 write ,value
是依赖于限定词的符号或数值。 缺省的限定词是trace. 使用 ' ! ' 将取反。例
如, -eopen 意思是 -e trace=open ,也就是只跟踪open调用。相反,
-etrace=!open 跟踪除open以外的所有系统调用。此外,关键字 all 和 none 也
有显而易见的用法。注意,一些shell使用 ' ! ' 作为history命令的扩展,如果
是这样,记得要使用转义符。
-e trace=set
只跟踪系统调用的特定集合。The
-c 选项对于确定跟踪哪些命令有意义很有帮助。 距离来说,trace=open,close,
read,write 意思是只跟踪这4个系统调用。注意当只监视了系统调用的一个子集合
时,则需要慎重判断用户/内核边界了。缺省值为trace=all。
-e trace=file
跟踪所有以文件名作为参数的系统调用。 可以认为这是 “-e
trace=open,stat,chmod,unlink”的简写。这可以观察目前进程正引用那个文件,
此外还可以确保不会漏掉lstat这样的。 Betchya woulda for got that one.
-e trace=process
跟踪包含进程管理功能的系统调用。这有助于观察进程的fork, wait,exec等动作。
-e trace=network
跟踪与网络相关的系统调用。
-e trace=signal
跟踪与信号相关的系统调用。
-e trace=ipc
跟踪与ipc相关的系统调用。
-e trace=desc
跟踪与文件描述符相关的系统调用。
-e abbrev=set
简化输出大数据结构。缺省是abbrev=all。‘-v’则是abbrev=none。
-e verbose=set
详细输出指定集合的系统调用。缺省是verbose=all。
-e raw=set
打印系统调用的原始未解码数据。当对解码不信任或需要了解具体数值的情况时使用。
-e signal=set
只跟踪特定的信号集合。缺省为 signal=all。例如,signal=!SIGIO表示SIGIO信
号不被跟踪。
-e read=set
将从指定集合所包含的fd读出的十六进制和ASCII数据全部导出。例如想观察所有
fd值为3和5上的输入动作,使用“ -e read=3,5”。注意它和正常跟踪read(2)系统
调用是无关的,后者由“-e trace=read”控制。
-e write=set
将从指定集合所包含的fd写入的十六进制和ASCII数据全部导出。例如想观察所有
fd值为3和5上的输出动作,使用“ -e write=3,5”。注意它和正常跟踪write(2)系
统调用是无关的,后者由“-e trace=write”控制。
-o filename
将跟踪信息写入文件而不是标准错误输出。如果使用了“-ff”,文件名则为
filename.pid。
-O overhead
指定跟踪系统调用的负载时间为overhead微秒。 在 '-c' 参数统计系统调用时间
时,这个参数将覆盖缺省估算strace本身统计消耗的负载值。
-p pid
挂接指定进程并开始跟踪。跟踪可以随时通过键盘信号中止(CTRL-C),strace将脱
离跟踪进程来回应。多个“-p”参数可以跟踪多个进程,最多可达32个。
-s strsize
指定最大打印字符串长度。(缺省 32). 注意,文件名例外,它将完全打印。
-S sortby
根据指定sortby标准对 '-c' 统计图排序。合法规则值为 time, calls, name, 或
nothing (缺省值time).
-u username
使用指定用户运行要跟踪的命令。 如果不使用这个选项,即使具有超级位的程序
也不能以有效的优先级执行。
-E var=val 根据 var=val 设定值运行命令。
-E var 在传递变量表前将var去掉。
SETUID 安装
如果strace以设置setuid给root的方式安装,那么将业已跟踪隶属于任何用户的程序。
此外setuid和setgid将以正确的有效权限执行。略...
其它:
ltrace(1), time(1), ptrace(2), proc(5)
NOTES
略...
BUGS
略...
TRANSBY
* Mon Dec 17 2007 Siyuan Wang
PROBLEMS
错误报告:.
名称
strace - 跟踪系统调用和信号
概要
strace [ -dffhiqrtttTvxx ] [ -a列值 ] [ -e表达式 ] ... [ -o文件名 ] [ -p
进程号 ] ... [ -s字符串长度 ] [ -u用户名 ] [ -E变量=val ] ... [ -E变量 ]
.... [ 命令 [ 参数 ... ] ]
strace -c [ -e表达式 ] ... [ -O总数 ] [ -S排序 ] [ 命令 [ 参数 ... ] ]
描述:
简单地说,strace就是运行一个特定的命令,直到它退出。它截取并记录进程产生
的系统调用和进程接收到的信号。每个系统调用,它的参数及其返回值将打印到标
准错误输出或通过-o选项保存到指定文件。
strace是很有用的分析,指导和调试工具。当面对那些源码并不可靠的程序时,系
统管理员,分析师和故障检测师们会发现strace是非常棒的,因为他们不需要重新
编译就可以跟踪了!学生,黑客以及那些喜欢猎奇的人们也会发现,仅仅通过跟踪
很普通的程序就可以对了解一个系统和它的系统调用很有帮助。由于系统调用和信
号是发生在用户/内核接口上的事件,这也使程序员们感觉到细致地检查这个边界
点对于分离bug,健壮性检测和捕捉瞬间状态很有用。
跟踪信息的每一行都包括系统调用的名称,它的参数跟在后面的()中,还有它的返
回值。例如,跟踪 'cat /dev/null' 这个命令其中有一行是:
open("/dev/null", O_RDONLY|O_LARGEFILE) = 3
而错误 (一般返回值为 -1) 有一个错误号和一个错误字串:
open("/foo/bar", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
信号是作为信号标识和信号字符串打印的。 跟踪并中断‘sleep 666‘时有一段是这
样的:
sigsuspend([]
--- SIGINT (Interrupt) ---
+++ killed by SIGINT +++
参数用带有情绪色彩的符号方式打印出来。
下面这个例子执行了‘‘>>xyzzy’’的重定向脚本:
open("xyzzy", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
在这里,open的3个参数形式通过分解标识符解码为3个按位与的成员并打印为传统
的8进制. 传统的用法和ANSI或POSIX不大一样,不过更倾向于使用后者。有些情况
下,strace的输出比源码可读性更好些。
结构指针会被复用并且其成员同样适当显示出来。所有情况下参数都会以尽可能像
C那样的格式表现。例如:命令‘‘ls -l /dev/null’’的核心部分捕捉为:
lstat("/dev/null", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
请注意‘struct stat’参数是如何被复用的,其成员是如何形象显示的。 另外成员
st_mode被细致地解码成了符号和数值的按位与。还要注意lstat的第一个参数是系
统调用的输入,跌入个则是输出。如果系统调用失败,则输出参数值不变,因此参
数并不是总被复用的。比如,再用‘‘ls -l’’列出一个不存在的文件 '/foo/bar
',会有如下输出:
lstat("/foo/bar", 0xb004) = -1 ENOENT (没有那个文件或目录)
在这种情况下复用是没必要的。
字符指针被复用并且并以C字符串形式显示出来。 字符串中的非打印字符一般用 C
转义符表示,不过仅仅打印第一组 strsize (缺省为32个) 大小字节的字符串;剩
下的用省略号代替。这里有一行‘‘ls -l’’命令输出,是调用getpwuid库读取密码
文件时的情况:
read(3, "root::0:0:System Administrator:/"..., 1024) = 422
除了结构使用()表示,简单的指针和数组则使用[]来表示,其中元素用 ' , ' 隔
开。这里的例子是跟踪‘‘id’’命令的输出:
getgroups(32, [100, 0]) = 2
另外, bit-sets 也使用[]表示,不过组元素只是用空格分开。这里是一个将要执
行外部命令的脚本:
sigprocmask(SIG_BLOCK, [CHLD TTOU], []) = 0
这里的第二个参数是有两个信号的 bit-set 。有时候 bit-set 元素太多,相反其
他非bit-set 元素更有打印价值,此时会表示如下:
sigprocmask(SIG_UNBLOCK, ~[], NULL) = 0
这里第二个参数代表整个bit-set。
选项
-c 为每个系统调用计算时间、调用次数和错误次数,并在程序退出时打印统计报
表。对于Linux来说,这表示的是系统时间 (运行在核心态时占用的CPU时间) ,独
立于时钟时间。如果 -c 和 -f 或 -F (如下)一同使用, 则只保留所有跟踪进程的
总和。
-d 把一些strace自身的调试信息显示到标准错误输出。
-f
跟踪当前进程通过fork系统调用派生的子进程。一旦获得子进程号,它将被跟踪
(通过父进程fork的返回值). 这意味着这种子进程将存在一个不可控期(尤其使用
vfork(2)的情况), 直到父进程再次规划好来完成这个 (v)fork(2) 调用。如果父
进程决定wait(2)一个正被跟踪的子进程,它将一直挂起,直到子进程终止或子进程
收到了使其终止的信号(当前子进程的信号处理情况决定).
-ff
如果同时使用了-o filename参数, 每个子进程调试信息都会记录到各自的
filename.pid 中。它与-c这个选项不兼容,因为 -c 是不保留单独进程记录的。
-F 尝试跟踪vfork. (在SunOS 4.x上, 使用一些动态链接技巧可以实现.)。否则,
即使使用-f参数,vfork也不会跟踪。
-h 打印帮助信息。
-i 在进行系统调用时打印指令指针地址。
-q 忽略attach, detach等信息。如果输出重定向到文件并且命令直接运行而不是
attach的,该选项自动启用。
-r 对每一个系统调用入口打印相对时间戳。这将记录两个连续的系统调用起始时
刻的时间差。
-t 在每一行信息前加入当前时间。
-tt 如果有两个t参数,当前时间将精确到微秒。
-ttt 如果有三个t参数, 当前时间将精确到微秒,并且整数部分将以1970年为基准
的秒数计算.
-T 记录花费在系统调用上的时间。这将记录每个系统调用从开始到结束的时间差。
-v 显示更详细信息。
-V 显示strace的版本号。
-x 打印十六进制格式的所有非ascii码。
-xx 以十六进制格式打印所有字符。
-a 以指定列值对齐打印返回值(缺省为第40列)
-e expr 限定表达式。它修改跟踪的事件以及如何跟踪它们。 表达式的格式为:
[限定词=][!]value1[,value2]...
限定词可以为 trace, abbrev, verbose, raw, signal, read 或 write ,value
是依赖于限定词的符号或数值。 缺省的限定词是trace. 使用 ' ! ' 将取反。例
如, -eopen 意思是 -e trace=open ,也就是只跟踪open调用。相反,
-etrace=!open 跟踪除open以外的所有系统调用。此外,关键字 all 和 none 也
有显而易见的用法。注意,一些shell使用 ' ! ' 作为history命令的扩展,如果
是这样,记得要使用转义符。
-e trace=set
只跟踪系统调用的特定集合。The
-c 选项对于确定跟踪哪些命令有意义很有帮助。 距离来说,trace=open,close,
read,write 意思是只跟踪这4个系统调用。注意当只监视了系统调用的一个子集合
时,则需要慎重判断用户/内核边界了。缺省值为trace=all。
-e trace=file
跟踪所有以文件名作为参数的系统调用。 可以认为这是 “-e
trace=open,stat,chmod,unlink”的简写。这可以观察目前进程正引用那个文件,
此外还可以确保不会漏掉lstat这样的。 Betchya woulda for got that one.
-e trace=process
跟踪包含进程管理功能的系统调用。这有助于观察进程的fork, wait,exec等动作。
-e trace=network
跟踪与网络相关的系统调用。
-e trace=signal
跟踪与信号相关的系统调用。
-e trace=ipc
跟踪与ipc相关的系统调用。
-e trace=desc
跟踪与文件描述符相关的系统调用。
-e abbrev=set
简化输出大数据结构。缺省是abbrev=all。‘-v’则是abbrev=none。
-e verbose=set
详细输出指定集合的系统调用。缺省是verbose=all。
-e raw=set
打印系统调用的原始未解码数据。当对解码不信任或需要了解具体数值的情况时使用。
-e signal=set
只跟踪特定的信号集合。缺省为 signal=all。例如,signal=!SIGIO表示SIGIO信
号不被跟踪。
-e read=set
将从指定集合所包含的fd读出的十六进制和ASCII数据全部导出。例如想观察所有
fd值为3和5上的输入动作,使用“ -e read=3,5”。注意它和正常跟踪read(2)系统
调用是无关的,后者由“-e trace=read”控制。
-e write=set
将从指定集合所包含的fd写入的十六进制和ASCII数据全部导出。例如想观察所有
fd值为3和5上的输出动作,使用“ -e write=3,5”。注意它和正常跟踪write(2)系
统调用是无关的,后者由“-e trace=write”控制。
-o filename
将跟踪信息写入文件而不是标准错误输出。如果使用了“-ff”,文件名则为
filename.pid。
-O overhead
指定跟踪系统调用的负载时间为overhead微秒。 在 '-c' 参数统计系统调用时间
时,这个参数将覆盖缺省估算strace本身统计消耗的负载值。
-p pid
挂接指定进程并开始跟踪。跟踪可以随时通过键盘信号中止(CTRL-C),strace将脱
离跟踪进程来回应。多个“-p”参数可以跟踪多个进程,最多可达32个。
-s strsize
指定最大打印字符串长度。(缺省 32). 注意,文件名例外,它将完全打印。
-S sortby
根据指定sortby标准对 '-c' 统计图排序。合法规则值为 time, calls, name, 或
nothing (缺省值time).
-u username
使用指定用户运行要跟踪的命令。 如果不使用这个选项,即使具有超级位的程序
也不能以有效的优先级执行。
-E var=val 根据 var=val 设定值运行命令。
-E var 在传递变量表前将var去掉。
SETUID 安装
如果strace以设置setuid给root的方式安装,那么将业已跟踪隶属于任何用户的程序。
此外setuid和setgid将以正确的有效权限执行。略...
其它:
ltrace(1), time(1), ptrace(2), proc(5)
NOTES
略...
BUGS
略...
TRANSBY
* Mon Dec 17 2007 Siyuan Wang
PROBLEMS
错误报告: