4. strace 常用选项详解:-c、-e、-p、-o、-f、-t、-T 等核心选项的功能与使用

strace 的强大之处在于其丰富的选项体系,能够精确控制跟踪的范围、输出格式与统计维度。掌握这些核心选项,是高效定位性能瓶颈的基础。本章将逐一剖析最常用的七个选项,并结合实战场景说明其适用条件。

strace 核心选项功能总览 strace 命令 -c 统计汇总 -e 过滤表达式 -p 附加进程 -o 输出到文件 -f 跟踪子进程 -t 时间戳 -T 系统调用耗时 提示:选项可组合使用,例如 strace -c -p 1234 或 strace -e trace=open,read -o trace.log ./app

4.1 -c:统计汇总模式

功能:跟踪结束后输出每个系统调用的调用次数、总耗时、平均耗时、错误次数等统计信息,而非逐行输出调用详情。

适用场景:快速评估程序整体系统调用开销分布,定位高频或高耗时调用。

示例:统计 ls 命令的系统调用分布

$ strace -c ls /tmp
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 30.12    0.000412          34        12           newfstatat
 22.45    0.000307          19        16           getdents64
 18.36    0.000251          31         8           write
 10.08    0.000138          17         8           close
  8.92    0.000122          15         8           openat
  5.67    0.000078          13         6           mmap
  4.40    0.000060          12         5           fstat
------ ----------- ----------- --------- --------- ----------------
100.00    0.001368                    63           total

输出字段解读:

字段含义分析价值
% time该调用耗时占总耗时的百分比快速定位热点调用
seconds该调用累计耗时(秒)量化绝对开销
usecs/call每次调用的平均微秒数判断单次调用是否异常
calls调用次数识别高频调用
errors错误次数发现潜在故障

实战技巧:当 % time 集中在少数几个系统调用上时,说明性能瓶颈很可能就在这些调用中。例如 write 占比过高,可能意味着 I/O 写入是瓶颈。

4.2 -e:过滤表达式

功能:通过表达式精确控制跟踪哪些系统调用或事件,大幅减少输出噪音。

常用表达式格式:

表达式含义示例
trace=syscall_set跟踪指定的一组系统调用-e trace=open,read,write
trace=file跟踪所有文件操作相关调用-e trace=file
trace=network跟踪所有网络相关调用-e trace=network
trace=process跟踪进程管理相关调用-e trace=process
trace=signal跟踪信号相关调用-e trace=signal
trace=ipc跟踪进程间通信调用-e trace=ipc
read=fd显示指定文件描述符的读取内容-e read=3
write=fd显示指定文件描述符的写入内容-e write=2

示例:仅跟踪文件打开和读取操作

$ strace -e trace=open,openat,read cat /etc/hostname
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/hostname", O_RDONLY) = 3
read(3, "my-server\n", 4096)            = 10
+++ exited with 0 +++

注意:-e trace=file 是一个便捷分类,包含 open、stat、read、write 等数十个文件相关调用。如果只想看某几个调用,务必使用逗号分隔的精确列表,避免输出过多无用信息。

4.3 -p:附加到指定进程

功能:跟踪一个已经运行的进程,而不是启动一个新程序。可以同时附加多个进程。

适用场景:线上服务进程出现异常或性能抖动时,无需重启即可动态跟踪。

示例:跟踪 PID 为 1234 的进程

$ strace -p 1234
strace: Process 1234 attached
restart_syscall(<... resuming interrupted call ...>) = 0
epoll_wait(5, [], 64, 1000)             = 0
epoll_wait(5, [], 64, 1000)             = 0
...(持续输出)

多进程附加:

$ strace -p 1234 -p 5678 -p 9012

实战技巧:线上跟踪时建议配合 -o 将输出写入文件,避免终端输出影响进程性能。同时使用 -f 跟踪子进程,捕获完整调用链。

4.4 -o:输出到文件

功能:将跟踪结果写入指定文件,而非标准错误输出(stderr)。

适用场景:跟踪输出量巨大时,便于后续分析;避免终端滚动影响操作。

示例:将跟踪结果保存到文件

$ strace -o /tmp/strace.log -e trace=network curl https://example.com
$ wc -l /tmp/strace.log
245 /tmp/strace.log

与 -ff 组合使用:当同时使用 -f 跟踪子进程时,-o 可以配合 -ff 为每个进程生成独立文件。

$ strace -o /tmp/strace -ff -e trace=file make -j4
$ ls /tmp/strace*
/tmp/strace.12345  /tmp/strace.12346  /tmp/strace.12347  /tmp/strace.12348

4.5 -f:跟踪子进程

功能:跟踪由当前进程通过 fork、vfork、clone 等系统调用创建的子进程。

适用场景:多进程架构的服务(如 Nginx、Apache)、使用 fork 的脚本、Make 构建系统等。

示例:跟踪 bash 及其子进程

$ strace -f -e trace=execve bash -c "echo hello; ls"
execve("/usr/bin/bash", ["bash", "-c", "echo hello; ls"], ...) = 0
strace: Process 23456 attached
[pid 23456] execve("/usr/bin/echo", ["echo", "hello"], ...) = 0
hello
[pid 23456] +++ exited with 0 +++
strace: Process 23457 attached
[pid 23457] execve("/usr/bin/ls", ["ls"], ...) = 0
...(ls 输出)

注意:-f 会大幅增加输出量,建议配合 -e 过滤和 -o 输出到文件使用,避免终端被淹没。

4.6 -t:时间戳

功能:在每行系统调用输出前添加时间戳,精确到秒或微秒。

三种变体:

选项时间格式示例输出
-t时:分:秒14:23:45 openat(...) = 3
-tt时:分:秒.微秒14:23:45.123456 openat(...) = 3
-tttUnix 时间戳.微秒1698765425.123456 openat(...) = 3

示例:使用微秒级时间戳分析调用时序

$ strace -tt -e trace=read,write cat /etc/hostname
14:23:45.123456 read(3, "my-server\n", 4096) = 10
14:23:45.123789 write(1, "my-server\n", 10) = 10
14:23:45.123912 read(3, "", 4096)      = 0

分析价值:通过时间戳可以计算两次调用之间的时间间隔,识别出程序在何处发生了长时间等待(如网络 I/O、锁等待)。

4.7 -T:显示系统调用耗时

功能:在每行系统调用输出的末尾,以尖括号形式显示该次调用的耗时(微秒)。

适用场景:精确测量每个系统调用的执行时间,定位单次调用中的性能异常。

示例:显示每次系统调用的耗时

$ strace -T -e trace=read,write cat /etc/hostname
read(3, "my-server\n", 4096)            = 10 <0.000012>
write(1, "my-server\n", 10)             = 10 <0.000025>
read(3, "", 4096)                       = 0 <0.000008>

实战技巧:将 -T 与 -tt 组合使用,可以同时获得绝对时间点和单次调用耗时,是定位慢调用的黄金组合。

$ strace -tt -T -e trace=read,write cat /etc/hostname
14:23:45.123456 read(3, "my-server\n", 4096) = 10 <0.000012>
14:23:45.123789 write(1, "my-server\n", 10) = 10 <0.000025>

4.8 选项组合实战案例

以下是一个综合使用多个选项定位性能瓶颈的典型场景:

案例:分析 Nginx worker 进程的 I/O 行为

# 1. 先使用 -c 快速评估整体开销分布
$ strace -c -p $(pgrep -n nginx)
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 45.23    0.892134          23     38792           epoll_wait
 22.15    0.436789          12     36399           writev
 18.67    0.368234          15     24556           recvfrom
  8.92    0.176001           8     22001           accept4
  5.03    0.099234           5     19876           close
------ ----------- ----------- --------- --------- ----------------
100.00    1.972234                141624           total

# 2. 发现 epoll_wait 耗时最高,进一步跟踪详细调用
$ strace -tt -T -e trace=epoll_wait -p $(pgrep -n nginx) -o /tmp/nginx_epoll.log

# 3. 分析日志中耗时超过 100ms 的 epoll_wait 调用
$ awk -F'[<>]' '{if ($2 > 100000) print}' /tmp/nginx_epoll.log
14:23:45.123456 epoll_wait(5, [], 64, 5000) = 1 <0.234567>
14:23:48.456789 epoll_wait(5, [], 64, 5000) = 1 <0.345678>

分析结论:epoll_wait 耗时超过 100ms 说明事件等待时间较长,可能原因是后端服务响应慢或连接池不足。结合 -e trace=recvfrom 进一步分析网络接收延迟,可以精确定位瓶颈点。

strace 选项组合决策流程 启动新程序? 是:直接 strace ./app 否:使用 -p PID 需要统计概览? 是:加 -c 否:加 -e 过滤 输出到文件:-o 加时间戳:-tt -T

4.9 选项速查表

选项功能常用组合性能影响
-c统计汇总模式-c -p PID低(仅汇总)
-e过滤系统调用-e trace=file,network低(减少输出)
-p附加到运行进程-p PID1 -p PID2中
-o输出到文件-o /tmp/log低
-f跟踪子进程-f -o /tmp/log高(输出量大)
-t/-tt/-ttt添加时间戳-tt -T低
-T显示调用耗时-T -e trace=read低

最佳实践总结:

  • 快速定位热点:strace -c -p PID → 根据 %time 确定瓶颈调用
  • 深入分析单类调用:strace -e trace=瓶颈调用 -tt -T -p PID -o log
  • 多进程服务:strace -f -e trace=file -o /tmp/log ./app
  • 线上安全跟踪:始终使用 -o 写入文件,避免终端 I/O 干扰