strace

跟踪进程执行时的系统调用和所接收的信号

追踪某个命令
会输出很多系统调用命令, 如下面, =左边是系统调用,右边是系统调用结果

 $strace ls -l      

能看到ls -l命令整个的系统调用情况
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=388, …}) = 0

语法

  strace [ -dDffhiqrtttTvVxx ] [ -a column ] [ -e expr ]... [ -o file ] [ -p pid ]... 
     [ -s strsize ] [ -u username ] [ -E var=val ]... [ -E var ]... [ command [ arg... ] ]

  strace -c [ -D ] [ -e expr ]... [ -O overhead ] [ -S sortby ] [ command [ arg... ] ] 

选项



   -a column
       设置返回值的输出位置.默认 为40.

   -c  统计每个系统调用的时间、调用和错误,并报告程序退出的摘要。
       在Linux上,这尝试显示独立于挂钟时间的系统时间(在内核中运行的CPU时间)。
       如果-c与-f或-f(下面)一起使用,则只保留所有跟踪进程的总计

   -D  (在SVR4和FreeBSD上不可用。)将跟踪进程作为独立的孙进程运行,
       不是tracee的父进程。这通过保持,减少了strace的可见效果
       跟踪调用过程的直接子项。

   -d  在标准错误上显示strace本身的一些调试输出

   -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=set
       只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all. 
   -e trace=file
       只跟踪有关文件操作的系统调用. 
   -e trace=process
       只跟踪有关进程控制的系统调用. 
   -e trace=network
       跟踪与网络有关的所有系统调用. 
   -e trace=signal
       跟踪所有与系统信号有关的 系统调用  
   -e trace=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(或signal =!io)会导致无法跟踪SIGIO信号。 
   -e read=set
       对从文件描述符读取的所有数据执行完整的十六进制和ASCII转储
       列在指定的集合中。例如,要查看文件中的所有输入活动
       描述符3和5使用-e read = 3,5。请注意,这与正常情况无关
       跟踪read(2)系统调用,该调用由选项-e trace = read控制。
   -e write=set
       对写入文件描述符的所有数据执行完整的十六进制和ASCII转储
       列在指定的集合中。例如,要查看文件中的所有输出活动
       描述符3和5使用-e write = 3,5。请注意,这与正常情况无关
       跟踪write(2)系统调用,该调用由选项-e trace = write控制

   -E var=val
       在其环境变量列表中运行带有var = val的命令。
   -E var
       从继承的环境变量列表中删除var,然后将其传递给命令。 

   -f  跟踪由fork调用所产生的子进程.

   -ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. .

   -F  此选项现已过时,它具有与-f相同的功能

   -h  打印帮助摘要

   -i 在系统调用时打印指令指针。

   -o filename
       将跟踪输出写入文件的文件名

   -O overhead
       设置用于跟踪系统调用到开销微秒的开销。
       这对于重写默认的启发式很有用,它可以用来猜测仅在使用-c选项测量计时系统调用时花费了多少时间。
       启发式算法的准确性可以通过在不跟踪(使用时间(1))的情况下对给定的程序进行计时,
       并将累计的系统调用时间与使用-c生成的总时间进行比较来衡量。

   -p pid
       跟踪指定的进程pid

   -q  禁止有关附加,分离等的消息。这在输出时自动发生
       被重定向到文件,命令直接运行而不是附加

   -r  在进入每个系统调用时打印相对时间戳。这记录了时间
       连续系统调用开始之间的差异。

   -s strsize
       指定要打印的最大字符串大小(默认值为32)。请注意,文件名是
       不考虑字符串,并始终打印完整。

   -S sortby
       按指定标准对由-c选项打印的直方图的输出进行排序。
       合法值是时间,呼叫,名称和任何内容(默认时间)。

   -t  使用一天中的时间为跟踪的每一行添加前缀。

   -tt 如果给出两次,则打印的时间将包括微秒。

   -ttt  如果给定三次,则打印的时间将包括微秒和前导部分
         将打印为自纪元以来的秒数。

   -T  显示系统调用所花费的时间。这记录了之间的时差
       每个系统调用的开始和结束。

   -u username
       使用用户ID,组ID和用户名的补充组运行命令。
       此选项仅在以root身份运行时才有用,并且能够正确执行
       setuid和/或setgid二进制文件。除非使用setuid和setgid程序这个选项
       没有有效的权限执行。

   -v  打印环境

   -V  打印strace的版本号

   -x  以十六进制字符串格式打印所有非ASCII字符串。

   -xx 以十六进制字符串格式打印所有字符串。

在最简单的情况下,strace运行指定的命令直到它退出。它拦截并记录由进程调用的系统调用和进程接收的信号。每个系统调用的名称,其参数和返回值都打印在标准错误或使用-o选项指定的文件上。

strace是一种有用的诊断,指导和调试工具。系统管理员,诊断工作者和故障排除者会发现它对于解决源代码不易获得的程序的问题非常宝贵,因为它们不需要重新编译以便跟踪它们。

学生,黑客和过于好奇的人会发现,通过跟踪普通程序,可以了解系统及其系统调用的大量信息。程序员会发现,由于系统调用和信号是在用户/内核接口发生的事件,因此仔细检查此边界对于错误隔离,健全性检查和尝试捕获竞争条件非常有用。

例子

追踪某个进程,需要带上-f来追踪所有子进程

$ strace -f -p 5926 -o /home/***/5926.strace.log

可以输出系统调用的统计结果,也就是每个命令的占比

$ strace -c -f -p 5926 -o /home/***/5926.strace.log

#less  /home/***/5926.strace.log
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 60.47   19.181735        7429      2582      1258 futex
 23.42    7.429387      212268        35        35 restart_syscall
 11.14    3.533856         983      3596           epoll_wait
  1.50    0.475396          51      9368           setsockopt
  0.79    0.250978          54      4684           fcntl
  0.72    0.227007          48      4684      2342 epoll_ctl
  0.42    0.132211          56      2342      2342 connect
  0.40    0.127517          54      2342           getsockopt
  0.39    0.123448          53      2342           close
  0.38    0.119249          51      2342           dup2
  0.37    0.117744          50      2342           socket
  0.00    0.000432          15        29           recvfrom
  0.00    0.000210           7        29           poll
  0.00    0.000000           0        10           write
  0.00    0.000000           0        29           sendto
------ ----------- ----------- --------- --------- ----------------
100.00   31.719170                 36756      5977 total  

输出系统调用花费时间 -T

$ strace -T -f -e trace=network  -p 9618 -o /home/A/desc.trace.9618
$ cat /home/A/desc.trace.9618
9700  getsockopt(76, SOL_SOCKET, SO_ERROR, [111], [4]) = 0 <0.000020>

打印系统调用的发生时间 -t

$ strace -f -t   -p 9618 -o /home/A/9618.strace
$ cat /home/A/9618.strace
9705  21:57:09 getsockopt(54, SOL_SOCKET, SO_ERROR, [111], [4]) = 0

可以指定某个系统调用,下面为追踪read的系统调用 -e expr

$ strace -f -e read -p 9618   -o 9618.read.log

追踪网络调用情况 -e trace=network

$ strace -f -t  -e trace=network  -p 9618 -o /home/A/desc.trace.9618.withouti
$ cat /home/A/desc.trace.9618.withouti
9705  21:57:09 getsockopt(54, SOL_SOCKET, SO_ERROR, [111], [4]) = 0
...

追踪open系统调用 -e trace=open

也可以trace=open,close,read,write
$ strace -e trace=open  -o a.txt.log

$ less a.txt.log
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib64/libtinfo.so.5", O_RDONLY)  = 3
open("/lib64/libpcre.so.0", O_RDONLY)   = 3
...

记录文件操作,-e trace=file

把5926对文件的操作记录下来,相当于trace=open.stat,chmod,unlink...
$strace -f -e trace=file -p 5926 -o 5926.file.trace.log

把关于进程的系统调用记录下来 -e trace=process

 把6259对process系统调用的操作记录下来,相当于trace=
$strace -f -e trace=process -p 6259 -o 6259.file.process.log

把关于进程的系统调用记录下来 -e trace=network

把5926对网络的系统调用记录下来
$strace -f -e trace=network -p 5926  -o 5926.network.log

把进程间通讯记录下来 -e trace=ipc

把5926对进程间通讯的系统调用记录下来
$strace -f -e trace=ipc -p 5926  -o 5926.ipc.log

strace 命令实例:

linux命令:strace -f -s 512 -v ls -l -l ls -v 512 -s -f strace strace -f -s 512 -v ls -lrootopen.com
linux命令:strace -f -s 512 -v ls -l -l ls -v 512 -s -f strace strace -f -s 512 -v ls -lrootopen.com
2018-04-22 20:58:48

linux命令:strace <name of the program> program> the of <name strace strace <name of the program>rootopen.com
linux命令:strace <name of the program> program> the of <name strace strace <name of the program>rootopen.com
2018-05-14 12:57:48

linux命令:straceprocessname(){ x=( $(pgrep "$@") ); [[ ${x[@]} ]] || return 1; strace -vf ${x[@]/#/-p }; } } }; ${x[@]/#/-p -vf strace 1; return || ]] ${x[@]} [[ ); "$@") $(pgrep x=( straceprocessname(){ straceprocessname(){ x=( $(pgrep "$@") ); [[ ${x[@]} ]] || return 1; strace -vf ${x[@]/#/-p }; }rootopen.com
linux命令:straceprocessname(){ x=( $(pgrep "$@") ); [[ ${x[@]} ]] || return 1; strace -vf ${x[@]/#/-p }; } } }; ${x[@]/#/-p -vf strace 1; return || ]] ${x[@]} [[ ); "$@") $(pgrep x=( straceprocessname(){ straceprocessname(){ x=( $(pgrep "$@") ); [[ ${x[@]} ]] || return 1; strace -vf ${x[@]/#/-p }; }rootopen.com
2018-02-10 19:54:48

linux命令:strace -ff -e trace=write -e write=1,2 -p SOME_PID SOME_PID -p write=1,2 -e trace=write -e -ff strace strace -ff -e trace=write -e write=1,2 -p SOME_PIDrootopen.com
linux命令:strace -ff -e trace=write -e write=1,2 -p SOME_PID SOME_PID -p write=1,2 -e trace=write -e -ff strace strace -ff -e trace=write -e write=1,2 -p SOME_PIDrootopen.com
2018-03-13 12:21:48

linux命令:strace php tias.php -e open,access 2>&1 | grep foo.txt foo.txt grep | 2>&1 open,access -e tias.php php strace strace php tias.php -e open,access 2>&1 | grep foo.txtrootopen.com
linux命令:strace php tias.php -e open,access 2>&1 | grep foo.txt foo.txt grep | 2>&1 open,access -e tias.php php strace strace php tias.php -e open,access 2>&1 | grep foo.txtrootopen.com
2018-05-10 08:08:48

linux命令:strace -ff -e write=1,2 -s 1024 -p PID 2>&1 | grep "^ |" | cut -c11-60 | sed -e 's/ //g' | xxd -r -p -p -r xxd | //g' 's/ -e sed | -c11-60 cut | |" "^ grep | 2>&1 PID -p 1024 -s write=1,2 -e -ff strace strace -ff -e write=1,2 -s 1024 -p PID 2>&1 | grep "^ |" | cut -c11-60 | sed -e 's/ //g' | xxd -r -prootopen.com
linux命令:strace -ff -e write=1,2 -s 1024 -p PID 2>&1 | grep "^ |" | cut -c11-60 | sed -e 's/ //g' | xxd -r -p -p -r xxd | //g' 's/ -e sed | -c11-60 cut | |" "^ grep | 2>&1 PID -p 1024 -s write=1,2 -e -ff strace strace -ff -e write=1,2 -s 1024 -p PID 2>&1 | grep "^ |" | cut -c11-60 | sed -e 's/ //g' | xxd -r -prootopen.com
2018-02-25 09:49:48

linux命令:strace -e write=1,2 -p $PID 2>&1 | sed -un "/^ |/p" | sed -ue "s/^.\{9\}\(.\{50\}\).\+/\1/g" -e 's/ //g' | xxd -r -p -p -r xxd | //g' 's/ -e "s/^.\{9\}\(.\{50\}\).\+/\1/g" -ue sed | |/p" "/^ -un sed | 2>&1 $PID -p write=1,2 -e strace strace -e write=1,2 -p $PID 2>&1 | sed -un "/^ |/p" | sed -ue "s/^.\{9\}\(.\{50\}\).\+/\1/g" -e 's/ //g' | xxd -r -prootopen.com
linux命令:strace -e write=1,2 -p $PID 2>&1 | sed -un "/^ |/p" | sed -ue "s/^.\{9\}\(.\{50\}\).\+/\1/g" -e 's/ //g' | xxd -r -p -p -r xxd | //g' 's/ -e "s/^.\{9\}\(.\{50\}\).\+/\1/g" -ue sed | |/p" "/^ -un sed | 2>&1 $PID -p write=1,2 -e strace strace -e write=1,2 -p $PID 2>&1 | sed -un "/^ |/p" | sed -ue "s/^.\{9\}\(.\{50\}\).\+/\1/g" -e 's/ //g' | xxd -r -prootopen.com
2018-05-09 15:59:48

linux命令:strace -e open zim 2>&1 1>/dev/null | fgrep ~ | fgrep -v "= -1" | cut -d'"' -f2 -f2 -d'"' cut | -1" "= -v fgrep | ~ fgrep | 1>/dev/null 2>&1 zim open -e strace strace -e open zim 2>&1 1>/dev/null | fgrep ~ | fgrep -v "= -1" | cut -d'"' -f2rootopen.com
linux命令:strace -e open zim 2>&1 1>/dev/null | fgrep ~ | fgrep -v "= -1" | cut -d'"' -f2 -f2 -d'"' cut | -1" "= -v fgrep | ~ fgrep | 1>/dev/null 2>&1 zim open -e strace strace -e open zim 2>&1 1>/dev/null | fgrep ~ | fgrep -v "= -1" | cut -d'"' -f2rootopen.com
2018-03-22 05:01:48

linux命令:strace -ff -e trace=file my_command 2>&1 | perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print' print' && 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ -ne perl | 2>&1 my_command trace=file -e -ff strace strace -ff -e trace=file my_command 2>&1 | perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print'rootopen.com
linux命令:strace -ff -e trace=file my_command 2>&1 | perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print' print' && 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ -ne perl | 2>&1 my_command trace=file -e -ff strace strace -ff -e trace=file my_command 2>&1 | perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print'rootopen.com
2018-03-03 16:06:48

linux命令:strace -ttvfo /tmp/logfile -s 1024 program program 1024 -s /tmp/logfile -ttvfo strace strace -ttvfo /tmp/logfile -s 1024 programrootopen.com
linux命令:strace -ttvfo /tmp/logfile -s 1024 program program 1024 -s /tmp/logfile -ttvfo strace strace -ttvfo /tmp/logfile -s 1024 programrootopen.com
2018-04-18 20:56:48

Linux的Bash命令行(A-Z排序)