2. strace 基础选项:-c 统计、-e 过滤、-o 输出文件、-p 附加进程

strace 是 Linux 系统调用跟踪的瑞士军刀。掌握其核心选项,能让你从海量输出中快速定位问题。本节聚焦四个最常用的基础选项:-c(统计)、-e(过滤)、-o(输出文件)和 -p(附加进程)。

2.1 -c:系统调用统计模式

-c 选项将 strace 从逐条输出模式切换为汇总统计模式。它不打印每次调用的细节,而是在程序退出时输出一张统计表,包含每个系统调用的调用次数、总耗时、平均耗时、错误次数等信息。

适用场景:性能瓶颈分析、系统调用热点识别、对比不同实现方式的系统开销。

统计输出字段解析

字段 含义 调试价值
% time 该调用耗时占总时间的百分比 快速定位最耗时的系统调用
seconds 该调用累计耗时(秒) 量化性能影响
usecs/call 每次调用的平均微秒数 判断单次调用效率
calls 调用次数 识别高频调用
errors 返回错误的次数 发现异常行为

使用示例

# 统计 ls 命令的系统调用分布
strace -c ls /tmp

# 输出示例(简化):
# % time     seconds  usecs/call     calls    errors syscall
# ------ ----------- ----------- --------- --------- ----------------
#  45.23    0.002345         234        10           read
#  22.15    0.001148         115        10           write
#  12.67    0.000657          66        10           openat
#   8.34    0.000432          43        10           close
#   6.51    0.000337          34        10           fstat
#   5.10    0.000264          26        10           mmap
# ------ ----------- ----------- --------- --------- ----------------
# 100.00    0.005183                    60           total
调试技巧:当 usecs/call 值异常偏高时(如 read 超过 1000 us),通常意味着 I/O 阻塞或磁盘性能问题。结合 -e trace=file 过滤文件相关调用,可以进一步缩小排查范围。
strace -c 统计模式工作流程 程序启动 strace 拦截系统调用 逐条记录(不输出) 程序退出 汇总统计表输出 分析热点与异常 strace -c 不输出逐条调用,仅在程序结束后输出汇总统计表,适合性能分析场景

2.2 -e:系统调用过滤表达式

-e 选项是 strace 最强大的过滤机制。它允许你只跟踪感兴趣的系统调用类别或特定调用,大幅减少输出噪音。

过滤表达式语法

表达式 含义 示例
trace=file 文件相关调用(open, read, write, close 等) strace -e trace=file ls
trace=process 进程管理调用(fork, exec, exit 等) strace -e trace=process ./app
trace=network 网络相关调用(socket, connect, send, recv 等) strace -e trace=network curl http://example.com
trace=signal 信号相关调用(kill, signal, sigaction 等) strace -e trace=signal ./daemon
trace=desc 文件描述符操作(dup, fcntl, poll 等) strace -e trace=desc ./server
trace=ipc 进程间通信(shm, sem, msg 等) strace -e trace=ipc ./ipc_app
read=fd 显示指定文件描述符的读取内容 strace -e read=3 ./app
write=fd 显示指定文件描述符的写入内容 strace -e write=1 ./app

组合过滤与否定过滤

# 只跟踪文件相关调用,但排除 close 调用
strace -e trace=file -e trace=!close ls /tmp

# 同时跟踪文件和网络调用
strace -e trace=file,network curl http://example.com

# 跟踪所有调用,但排除 write 和 read(减少输出量)
strace -e trace=!write,read ./app
注意:过滤表达式中的 ! 表示排除。排除 write 和 read 可以大幅减少输出,但可能错过 I/O 相关的性能问题。建议先不加过滤运行一次,确认问题范围后再针对性过滤。
strace -e 过滤表达式分类 -e trace= 过滤 file 文件 process 进程 network 网络 signal 信号 ipc 通信 高级过滤组合 • 组合过滤:-e trace=file,network 同时跟踪文件和网络调用 • 否定过滤:-e trace=!write,read 排除 write 和 read 调用 • 内容显示:-e read=3,write=1 显示 fd 3 的读取和 fd 1 的写入内容

2.3 -o:输出到文件

默认情况下,strace 将输出发送到 stderr。使用 -o 选项可以将输出重定向到指定文件,便于后续分析、搜索和保存。

基本用法

# 将跟踪输出保存到文件
strace -o /tmp/strace.log ls /tmp

# 查看输出文件
cat /tmp/strace.log | head -20

# 结合 -c 使用,将统计结果保存到文件
strace -c -o /tmp/strace_stat.log ls /tmp

文件输出最佳实践

场景 推荐做法 说明
长时间跟踪 strace -o trace.log -p PID 避免终端输出被淹没,文件可随时查看
对比分析 strace -o before.log ./v1
strace -o after.log ./v2
使用 diff 对比两个版本的调用差异
结合 grep 搜索 strace -o trace.log ./app; grep "ENOENT" trace.log 快速定位文件不存在等错误
分卷输出 使用 -o file -ff(多进程) 每个子进程生成独立文件
调试技巧:使用 -o 结合 -e trace=file 和 grep,可以快速找出程序打开了哪些配置文件:
strace -o /tmp/trace.log -e trace=file ./app; grep -E "open(at)?\(" /tmp/trace.log | grep -v "ENOENT"

2.4 -p:附加到运行中的进程

-p 选项允许 strace 附加到已经运行的进程,而不是启动新程序。这是调试线上服务、守护进程和长时间运行程序的关键功能。

基本用法

# 附加到 PID 为 1234 的进程
strace -p 1234

# 附加到多个进程
strace -p 1234 -p 5678

# 附加到进程并过滤输出
strace -p 1234 -e trace=network

# 附加到进程,统计模式
strace -p 1234 -c

# 附加到进程,输出到文件
strace -p 1234 -o /tmp/nginx_trace.log

附加进程的注意事项

  • 权限要求:需要与目标进程相同的用户 ID 或 root 权限
  • 性能影响:附加 strace 会使每个系统调用增加约 50-200 微秒的开销
  • 信号影响:附加时会给目标进程发送 SIGSTOP,分离时发送 SIGCONT
  • 分离方式:按 Ctrl+C 或 Ctrl+D 分离,目标进程继续运行
  • 单线程限制:默认只跟踪主线程,使用 -f 跟踪子线程
生产环境警告:在生产服务器上对高并发进程(如数据库、Web 服务器)使用 strace -p 时,性能下降可能达到 10-100 倍。建议在以下情况使用:
1. 低峰期操作
2. 只过滤特定调用(如 -e trace=network)
3. 使用 -c 统计模式而非逐条输出
4. 设置超时时间,如 timeout 10 strace -p PID
strace -p 附加进程调试流程 运行中的进程 PID: 1234 strace -p 1234 附加跟踪 系统调用拦截 实时输出 Ctrl+C 分离 进程继续运行 附加 strace 后进程性能会下降,分离后恢复正常。建议使用 -e 过滤减少输出量。

2.5 选项组合实战

实际调试中,这四个选项经常组合使用。以下是一些典型场景的完整命令:

# 场景1:分析 Nginx worker 进程的网络调用
strace -p $(pgrep -f 'nginx: worker') -e trace=network -o /tmp/nginx_net.log

# 场景2:统计 MySQL 查询相关的文件操作
strace -p $(pidof mysqld) -c -e trace=file -o /tmp/mysql_file_stat.log

# 场景3:跟踪新启动的进程,只输出错误调用
strace -e trace=!write,read -o /tmp/errors.log ./app 2>&1 | grep -E "= -1|ENOENT|EACCES"

# 场景4:长时间跟踪并自动分离(使用 timeout)
timeout 30 strace -p 1234 -e trace=file -o /tmp/30sec_trace.log
核心要点回顾:
• -c:统计模式,适合性能分析,不输出逐条调用
• -e:过滤表达式,减少输出噪音,支持组合和否定
• -o:输出到文件,便于保存和后续分析
• -p:附加到运行中进程,调试线上服务的关键
• 组合使用时,先加 -e 过滤,再加 -o 输出,最后加 -p 或程序名