Strace工具基本使用

Strace Usage

Strace工具基本使用
Page content

程序运行Debug实用工具ltrace和strace

ltrace 库调用追踪器,追踪一个进程运行过程中调用了哪些库函数(function), ltrace也可以追踪系统调用和信号

strace 追踪一个进程运行过程中与哪些系统调用和信号有交互, strace 依赖于Linux下的系统调用ptrace(man 2 ptrace),同样ltrace工具也 有对ptrace系统调用的依赖

在linux下,对系统调用的说明手册在第2章,在使用手册时使用

~# man 2 SYSCALL
如:
~# man 2 execve  # 系统调用名
~# man 2 read
~# man 2 open

在linux下,对库函数调用的说明手册在第3章,在使用手册时使用

~# man 3 FUNC
如:
~# man 3 malloc   # 库函数名
~# man 3 opendir 
~# man 3 readdir

strace 使用

比如高频使用的ls命令,该命令会首先调用limux系统的glibc库函数,由glibc库来调用系统调用, 最后由系统调用处理相应的任务。即:

Command -----> glibc -----> system call

可以使用ltrace跟上命令来查看调用了哪些glibc的库函数,ltrace和strace的用法类似,此处先 说明strace的用法及输出解释。

  1. 直接跟命令,打印出该命令运行的进程所作的系统调用情况(系统调用名,传入的参数,返回值)
[root@server01 opt]# strace ls test/
execve("/usr/bin/ls", ["ls", "test/"], 0x7fff8ace9468 /* 30 vars */) = 0
......  # 省略了一大段
ioctl(1, TIOCGWINSZ, {ws_row=27, ws_col=172, ws_xpixel=0, ws_ypixel=0}) = 0
stat("test/", {st_mode=S_IFDIR|0755, st_size=60, ...}) = 0  # man 2 stat: 获取文件状态信息
openat(AT_FDCWD, "test/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents(3, /* 6 entries */, 32768)     = 160
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0  # 关闭文件描述符3
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f150b36d000
write(1, "syscall  syscall.c  tee  too\n", 29syscall  syscall.c  tee  too) = 29   # 写内容到标准输出(第一个参数为1,表示标准输出,也就是终端)
close(1)                                = 0    # 关闭标准输出文件描述符
munmap(0x7f150b36d000, 4096)            = 0
close(2)                                = 0    # 关闭标准错误文件描述符
exit_group(0)                           = ?
+++ exited with 0 +++

解释1:

execve("/usr/bin/ls", ["ls", "test/"], 0x7fff8ace9468 /* 30 vars */) = 0
  • execve: 系统调用名称
  • ("...", [...], ...): 传递了三个参数给该系统调用
  • = 0: 该系统调用返回值为0

上面的输出所涉及到的系统调用都是为了能让ls命令能够运行所必要的调用,系统调用大致可以 分为以下几类:

  • 进程管理系统调用
  • 文件系统管理系统调用
  • 网络和时间系统调用
  • IPC进程间通讯和信号处理系统调用
  • 信息收集系统调用

解释2:

openat(AT_FDCWD, "test/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3

该系统调用为openat,和系统调用open的功能一样,注意等号后面的数字3,为 该系统调用返回的值,表示打开的文件描述符为3.

解释3:

getdents(3, /* 6 entries */, 32768)     = 160
getdents(3, /* 0 entries */, 32768)     = 0

getdents系统调用会根据提供的文件描述符(此处为即其第一个参数3)获取目录入口,其为打开目录 做准备工作. 文件描述符是系统调用openat得到的.

解释4:

write(1, "syscall  syscall.c  tee  too\n", 29syscall  syscall.c  tee  too) = 29   # 写内容到标准输出(第一个参数为1,表示标准输出,也就是终端)

write 系统调用将得到的内容写到文件描述符1,即标准输出.

  1. 显示更加详细的信息加-v选项
~# strace -v ls test/

部分系统调用的信息会更加详细如:getdents,fstat,ioctl等

  1. 追踪当前进程产生的子进程使用-f
~# strace -f ls test/
  1. 使用列表的形式显示简要信息使用-c
~# strace -c ls test/
[root@server01 opt]# strace -c ls test/
syscall  syscall.c  tee  too                                # 命令的标准输出
% time     seconds  usecs/call     calls    errors syscall  # 分别是时间占比,时间,调用次数和错误次数
------ ----------- ----------- --------- --------- ----------------
 15.56    0.000347          19        18           mprotect
 15.34    0.000342          11        30           mmap
 14.13    0.000315          12        26        14 open
  9.01    0.000201          13        15           close
  8.03    0.000179          14        12           read
  7.31    0.000163          12        13           fstat
  5.29    0.000118          29         4           munmap
  2.83    0.000063          31         2         2 statfs
  2.74    0.000061          10         6         4 stat
  2.60    0.000058          29         2           getdents
  2.38    0.000053          26         2           rt_sigaction
  2.38    0.000053          26         2           ioctl
  2.33    0.000052          17         3           brk
  1.57    0.000035          35         1           write
  1.52    0.000034          17         2         1 access
  1.26    0.000028          28         1           openat
  1.21    0.000027          27         1           getrlimit
  1.21    0.000027          27         1           arch_prctl
  1.12    0.000025          25         1           rt_sigprocmask
  1.12    0.000025          25         1           set_tid_address
  1.08    0.000024          24         1           set_robust_list
  0.00    0.000000           0         1           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0.002230                   145        21 total
  1. 使用-e选项专注于特定的系统调用,多个系统调用使用逗号隔开即可
[root@server01 opt]# strace -e stat ls test/
stat("/apps/postgresql/lib/tls/x86_64", 0x7ffee7af0a80) = -1 ENOENT (No such file or directory)
stat("/apps/postgresql/lib/tls", 0x7ffee7af0a80) = -1 ENOENT (No such file or directory)
stat("/apps/postgresql/lib/x86_64", 0x7ffee7af0a80) = -1 ENOENT (No such file or directory)
stat("/apps/postgresql/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned", 0x7ffee7af1df0) = -1 ENOENT (No such file or directory)
stat("test/", {st_mode=S_IFDIR|0755, st_size=60, ...}) = 0
syscall  syscall.c  tee  too
+++ exited with 0 +++