strace

strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

常用参数

[root@iz2zecj7a5r32f2axsctb9z ~]# strace cat /dev/null
execve("/usr/bin/cat", ["cat", "/dev/null"], 0x7ffc02424dc8 /* 21 vars */) = 0
brk(NULL)                               = 0x2605000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2a2039f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (没有那个文件或目录)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=43859, ...}) = 0
mmap(NULL, 43859, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2a20394000
close(3)                                = 0

每一行都是一条系统调用,等号左边是系统调用的函数名及其参数,右边是该调用的返回值
strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。

-a column 设置返回值的输出位置.默认 为40
-i 输出系统调用的入口指针
-k 在每一次系统调用后打印出跟踪进程的执行栈
-o filename 将跟踪输出到文件
-A 文件追加模式
-q 禁止输出关于脱离的消息
-r 打印出相对时间关于每一个系统调用
-s strsize 当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节.文件名一直全部输出.
-t 在输出中的每一行前加上时间信息
-tt 在输出中的每一行前加上时间信息,微秒级
-ttt 微秒级输出,以秒表示时间
-T 显示每一调用所耗的时间
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-X format[raw] 设置常量和标记的打印格式
-y 打印出文件描述符关联的路径
-yy 打印出socket描述符关联的协议
-c 统计每一系统调用所执行的时间,次数和出错的次数等
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-d 输出strace关于标准错误的调试信息
-f 跟踪由fork调用所产生的子进程
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪
-i 输出系统调用的入口指针
-V 输出strace的版本信息
-e expr 指定一个表达式,用来控制如何跟踪.格式如下:

[qualifier=][!]value1[,value2]…
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-e open等价于 -e trace=open,表示只跟踪open调用.而-e trace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\.

-e trace=set 只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=/regex 只跟踪匹配表达式的系统调用
-e trace=file 只跟踪有关文件操作的系统调用
-e trace=process 只跟踪有关进程控制的系统调用
-e trace=network 跟踪与网络有关的所有系统调用
-e trace=signal 跟踪所有与系统信号有关的 系统调用
-e trace=ipc 跟踪所有与进程通讯有关的系统调用
-e trace=memory 跟踪所有与系统调用关联的内存映射
-e abbrev=set 设定 strace输出的系统调用的结果集.-v 等于 abbrev=none.默认为abbrev=all
-e raw=set 将指定的系统调用的参数以十六进制显示
-e signal=set 指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号
-e read=set 输出从指定文件中读出 的数据.例如: -e read=3,5
-e write=set 输出写入到指定文件中的数据
-p pid 跟踪指定的进程pid
-u username 以username 的UID和GID执行被跟踪的命令

实战

  1. strace的输出是标准输出(1),还是标准错误输出(2)

    [root@iz2zecj7a5r32f2axsctb9z shell]# strace -e trace=write strace ls
    ...
    write(2, "execve(\"/usr/bin/ls\", [\"ls\"], 0x"..., 58execve("/usr/bin/ls", ["ls"], 0x7ffe84928f30 /* 22 vars */) = 58
    --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=13742, si_uid=0, si_status=SIGTRAP, si_utime=0, si_stime=0} ---
    ...

    strace 输出是标准错误输出, 因此在将结果通过管道传递给其他命令时需要特别注意

  2. 寻找被程序读取的配置文件
    strace输出结果是输出到标准错误2的,当做debug信息了。而|管道传递给grep的只是标准输出1 ,若不加转换则grep 筛选不起作用(标准输出为空)。所以必须要加上“2>&1”,要把标准错误的信息先重定向到标准输出1。否则会全部输出。

    strace php 2>&1 | grep php.ini

[root@iz2zecj7a5r32f2axsctb9z shell]# strace php 2>&1 | grep php.ini
open("/usr/local/php/bin/php.ini", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
open("/usr/local/php/lib/php.ini", O_RDONLY) = 3
  1. 跟踪ls程序,查看访问了哪些文件

    strace -tt -T -f -e trace=file -s 1024 2>&1 ls

[root@iz2zecj7a5r32f2axsctb9z shell]# strace -tt -T -f -e trace=file -s 1024 2>&1 ls
17:58:24.954556 execve("/usr/bin/ls", ["ls"], 0x7ffe2ee23988 /* 22 vars */) = 0 <0.000146>
17:58:24.955195 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (没有那个文件或目录) <0.000012>
17:58:24.955458 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000012>
17:58:24.955633 open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 <0.000012>
17:58:24.955951 open("/lib64/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3 <0.000013>
17:58:24.956192 open("/lib64/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3 <0.000013>
17:58:24.956447 open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000021>
17:58:24.956713 open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3 <0.000013>
17:58:24.956941 open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 <0.000012>
17:58:24.957213 open("/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3 <0.000013>
17:58:24.957438 open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 <0.000013>
17:58:24.958645 statfs("/sys/fs/selinux", 0x7fff1f181530) = -1 ENOENT (没有那个文件或目录) <0.000017>
17:58:24.958724 statfs("/selinux", 0x7fff1f181530) = -1 ENOENT (没有那个文件或目录) <0.000010>
17:58:24.958908 open("/proc/filesystems", O_RDONLY) = 3 <0.000018>
17:58:24.959078 stat("/etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned", 0x7fff1f180a70) = -1 ENOENT (没有那个文件或目录) <0.000012>
17:58:24.959244 access("/etc/selinux/config", F_OK) = 0 <0.000012>
17:58:24.959352 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000013>
17:58:24.959647 openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3 <0.000012>
0  1.php  1.sh    a  a.c    align  align.c    a.php  arp  arp.c  linux  linux-shell  makefile
17:58:24.960452 +++ exited with 0 +++
  1. 跟踪指定进程

    strace -fv -e trace=all -p 723

[root@iz2zecj7a5r32f2axsctb9z tcp]# strace -fv -e trace=all -p 723 
strace: Process 723 attached
rt_sigsuspend([], 8
  1. 统计概要

    strace -c ls

[root@iz2zecj7a5r32f2axsctb9z tcp]# strace -c ls
tcpclient  tcpclient.c    tcpserver  tcpserver.c    tools.c  tools.h
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 11.86    0.000021           2        10           read
 10.73    0.000019           6         3           munmap
 10.17    0.000018           1        11           open
  9.60    0.000017           8         2           getdents
  7.91    0.000014           0        18           mprotect
  7.34    0.000013           6         2         2 statfs
  6.78    0.000012           0        14           close
  5.65    0.000010          10         1           write
  5.65    0.000010           0        28           mmap
  3.95    0.000007           3         2           ioctl
  3.39    0.000006           0        12           fstat
  2.82    0.000005           5         1         1 stat
  2.82    0.000005           2         2         1 access
  2.26    0.000004           1         3           brk
  2.26    0.000004           2         2           rt_sigaction
  2.26    0.000004           4         1           openat
  1.69    0.000003           3         1           rt_sigprocmask
  1.13    0.000002           2         1           getrlimit
  1.13    0.000002           2         1           set_tid_address
  0.56    0.000001           1         1           set_robust_list
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.000177                   118         4 total
  1. 查看网络连接失败原因

    strace -e poll,select,connect,recvfrom,sendto nc www.baidu.com 80

文档更新时间: 2021-03-02 19:54   作者:周国强