strace 完全使用指南
·6 mins
strace 完全使用指南 #
目录 #
1. strace 简介 #
1.1 什么是 strace #
strace 是 Linux 系统下的系统调用跟踪工具,它可以:
- 监控进程执行的所有系统调用
- 显示系统调用的参数和返回值
- 统计系统调用的执行时间和频率
- 跟踪信号传递过程
- 分析程序的系统级行为
1.2 主要用途 #
性能分析 → 找出系统调用瓶颈
故障排查 → 定位程序异常原因
安全审计 → 监控程序系统访问
逆向分析 → 理解程序运行机制
系统调优 → 优化系统调用使用
2. 基础语法 #
2.1 命令格式 #
# 基础语法
strace [选项] [命令]
strace [选项] -p <进程ID>
# 示例
strace ls /tmp # 跟踪 ls 命令
strace -p 1234 # 跟踪进程ID为1234的进程
strace -e trace=network curl baidu.com # 只跟踪网络相关系统调用
2.2 两种使用模式 #
模式1:启动新进程并跟踪
strace ./my_program
strace -o trace.log ./my_program
模式2:附加到已运行的进程
strace -p $(pgrep program_name)
strace -p 1234
3. 核心参数详解 #
3.1 进程相关参数 #
| 参数 | 含义 | 示例 |
|---|---|---|
-p <pid> | 附加到指定进程ID | strace -p 1234 |
-f | 跟踪子进程 | strace -f ./parent_program |
-F | (已废弃)跟踪vfork创建的子进程,现代strace中 -f 已涵盖fork/vfork/clone,-F 等同于 -f | strace -f ./program |
-ff | 为每个进程创建单独的输出文件 | strace -ff -o trace ./program |
使用示例:
# 跟踪多进程程序
strace -f -o multi_process.trace ./nginx
# 为每个进程单独输出
strace -ff -o trace_ ./multi_thread_app
# 生成: trace_1234, trace_1235, trace_1236...
3.2 输出控制参数 #
| 参数 | 含义 | 示例 |
|---|---|---|
-o <file> | 输出到文件 | strace -o output.log ./program |
-s <size> | 字符串显示长度 | strace -s 1024 ./program |
-v | 详细模式 | strace -v ./program |
-x | 十六进制显示非ASCII字符 | strace -x ./program |
-xx | 所有字符串都用十六进制 | strace -xx ./program |
字符串显示对比:
# 默认显示 (截断)
read(3, "Hello World"..., 1024) = 11
# 增加显示长度
strace -s 1024 ./program
read(3, "Hello World! This is a long string...", 1024) = 38
# 十六进制显示
strace -x ./program
read(3, "Hello\x20World\x21", 12) = 12
4. 过滤和跟踪选项 #
4.1 系统调用过滤 #
4.1.1 基本过滤语法 #
# 只跟踪指定的系统调用
strace -e trace=<syscall_set> ./program
# 排除指定的系统调用
strace -e trace=!<syscall_set> ./program
4.1.2 系统调用分类 #
| 分类 | 含义 | 包含的系统调用 |
|---|---|---|
file | 文件操作 | open, read, write, close, stat |
process | 进程管理 | fork, exec, exit, wait |
network | 网络操作 | socket, bind, listen, accept, send, recv |
signal | 信号处理 | kill, signal, sigaction |
ipc | 进程间通信 | pipe, msgget, semget, shmget |
desc | 文件描述符 | select, poll, epoll |
memory | 内存管理 | mmap, munmap, brk, mprotect |
使用示例:
# 只跟踪网络相关系统调用
strace -e trace=network ./network_app
# 跟踪文件和网络操作
strace -e trace=file,network ./web_server
# 排除内存管理相关调用
strace -e trace=!memory ./program
# 跟踪特定的系统调用
strace -e trace=read,write,open,close ./file_processor
4.2 高级过滤选项 #
4.2.1 错误过滤 #
# 只显示失败的系统调用
strace -e trace=all -e fault=eperm ./program
# 只显示返回错误的调用
strace -Z ./program
# 跟踪特定错误码
strace -e trace=all -e abbrev=none -e verbose=all ./program
4.2.2 文件描述符过滤 #
# 只跟踪特定文件描述符的操作
strace -e write=1,2 ./program # 只跟踪stdout和stderr
strace -e read=0 ./program # 只跟踪stdin读取
5. 输出格式控制 #
5.1 时间相关参数 #
| 参数 | 含义 | 输出格式 |
|---|---|---|
-t | 显示时间戳 | HH:MM:SS |
-tt | 显示微秒级时间戳 | HH:MM:SS.microseconds |
-ttt | 显示Unix时间戳 | seconds.microseconds |
-T | 显示系统调用耗时 | <0.000123> |
-r | 显示相对时间 | 自上次系统调用的时间间隔 |
时间输出示例:
# 标准时间戳
strace -t ./program
14:30:25 open("/etc/passwd", O_RDONLY) = 3
# 微秒级精度
strace -tt ./program
14:30:25.123456 open("/etc/passwd", O_RDONLY) = 3
# 显示执行时间
strace -T ./program
open("/etc/passwd", O_RDONLY) = 3 <0.000089>
# 相对时间
strace -r ./program
0.000000 open("/etc/passwd", O_RDONLY) = 3
0.000234 read(3, "root❌0:0:root:/root:/bin/bash\n", 4096) = 32
5.2 输出详细程度 #
# 详细模式 - 显示完整的结构体内容
strace -v ./program
# 简化模式 - 省略常见结构体的详细信息
strace -e abbrev=all ./program
# 自定义省略
strace -e abbrev=read,write ./program
对比示例:
# 默认输出
stat("/tmp", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
# 详细输出
strace -v ./program
stat("/tmp", {st_dev=makedev(0, 24), st_ino=2, st_mode=S_IFDIR|0755,
st_nlink=18, st_uid=0, st_gid=0, st_rdev=makedev(0, 0),
st_size=4096, st_blksize=4096, st_blocks=8, ...}) = 0
6. 性能分析参数 #
6.1 统计分析 #
# 生成系统调用统计报告
strace -c ./program
# 按时间排序
strace -c -S time ./program
# 按调用次数排序
strace -c -S calls ./program
# 按调用名称排序
strace -c -S name ./program
统计输出示例:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.98 0.017711 17711 1 restart_syscall
0.02 0.000004 4 1 futex
------ ----------- ----------- --------- --------- ----------------
100.00 0.017715 8857 2 total
6.2 性能监控参数 #
| 参数 | 含义 | 用途 |
|---|---|---|
-c | 统计模式 | 生成调用次数和时间统计 |
-C | 统计+详细模式 | 同时输出详细调用跟踪和汇总统计信息 |
-S <sort> | 排序方式 | time/calls/name/nothing |
-w | 总结挂起的系统调用 | 显示被阻塞的调用 |
7. 实用场景示例 #
7.1 网络程序分析 #
# 分析网络程序的系统调用
strace -e trace=network -tt -T -o network.log ./web_server
# 只关注socket操作
strace -e trace=socket,bind,listen,accept,send,recv ./network_app
# 分析连接建立过程
strace -e trace=network -v ./client_program
7.2 文件I/O分析 #
# 跟踪文件操作
strace -e trace=file -s 256 ./file_processor
# 查看配置文件读取
strace -e trace=openat,read -e file ./config_reader
# 分析写入性能
strace -e trace=write -T ./data_writer
7.3 性能瓶颈定位 #
# 找出最耗时的系统调用
strace -c -S time ./slow_program
# 分析高频系统调用
strace -c -S calls ./busy_program
# 监控长时间运行的进程
strace -p $(pgrep long_running) -c -T
7.4 多进程程序调试 #
# 跟踪父子进程
strace -f -o family.log ./parent_process
# 为每个进程单独输出
strace -ff -o trace_ ./multi_process_app
# 跟踪线程创建
strace -f -e trace=clone ./threaded_app
7.5 SSL/TLS程序分析 #
基于我们前面的实际案例:
# 分析HTTPS连接过程
strace -e trace=network,file -s 1024 ./https_client
# 查看证书读取过程
strace -e trace=openat,read -e file=/etc/ssl ./ssl_app
# 分析TLS握手
strace -e trace=sendto,recvfrom -x ./tls_client
8. 输出解读指南 #
8.1 系统调用格式 #
系统调用名(参数1, 参数2, ...) = 返回值 <执行时间>
示例解析:
# 文件打开
openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
# ↑ ↑ ↑ ↑
# 调用名 工作目录 文件路径 返回的文件描述符
# 网络发送
sendto(16, "\26\3\1\2\0\1\0\1\374...", 517, MSG_NOSIGNAL, NULL, 0) = 517
# ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
# 调用名 fd 数据内容 长度 标志 地址 长度 返回值
# 轮询等待
poll([{fd=16, events=POLLIN}], 1, 167) = 1 ([{fd=16, revents=POLLIN}])
# ↑ ↑ ↑ ↑ ↑ ↑ ↑
# 调用名 文件描述符 关注事件 数量 超时 返回数量 实际事件
8.2 常见返回值含义 #
| 返回值 | 含义 | 示例 |
|---|---|---|
> 0 | 成功,返回字节数/描述符等 | read() = 1024 |
0 | 成功,特殊含义 | read() = 0 (EOF) |
-1 | 失败 | open() = -1 ENOENT |
? | 进程退出/信号中断 | read() = ? ERESTART |
8.3 常见错误码 #
| 错误码 | 含义 | 常见原因 |
|---|---|---|
ENOENT | 文件不存在 | 路径错误、文件被删除 |
EACCES | 权限不足 | 文件权限、SELinux |
EAGAIN | 资源暂时不可用 | 非阻塞I/O、资源忙 |
EINPROGRESS | 操作正在进行 | 非阻塞connect |
EINTR | 被信号中断 | 信号处理 |
EPIPE | 管道破裂 | 对端关闭连接 |
9. 性能调优技巧 #
9.1 减少strace开销 #
# 只跟踪必要的系统调用
strace -e trace=network ./program
# 使用统计模式减少输出
strace -c ./program
# 限制字符串长度
strace -s 64 ./program
# 输出到文件而不是终端
strace -o output.log ./program
9.2 大量数据处理 #
# 使用压缩输出
strace -o >(gzip > trace.gz) ./program
# 分离错误输出
strace -o trace.out 2>trace.err ./program
# 实时监控关键调用
strace -e trace=network -f ./program | grep -E "(send|recv)"
9.3 长期监控 #
# 周期性统计
while true; do
timeout 60 strace -c -p $(pgrep myapp) 2>&1 | \
tee -a stats_$(date +%H%M).log
sleep 300
done
# 监控特定条件
strace -e trace=all -p $(pgrep myapp) 2>&1 | \
awk '/ENOENT/ {print strftime("%Y-%m-%d %H:%M:%S"), $0}'
10. 最佳实践 #
10.1 调试最佳实践 #
# 1. 从统计开始
strace -c ./program
# 2. 定位问题系统调用
strace -e trace=network -T ./program
# 3. 详细分析特定调用
strace -e trace=sendto,recvfrom -v -s 1024 ./program
# 4. 时间序列分析
strace -tt -T -o detailed.log ./program
10.2 性能分析最佳实践 #
# 对比分析
strace -c ./old_version > old_stats.txt
strace -c ./new_version > new_stats.txt
diff old_stats.txt new_stats.txt
# 瓶颈定位
strace -c -S time ./program | head -10
# 热点分析
strace -c -S calls ./program | head -10
10.3 生产环境使用注意事项 #
10.3.1 性能影响 #
# strace会显著影响程序性能,生产环境谨慎使用
# 建议:
# 1. 短时间跟踪
timeout 30 strace -p $PID
# 2. 只跟踪关键调用
strace -e trace=network -p $PID
# 3. 使用统计模式
strace -c -p $PID
10.3.2 安全考虑 #
# 避免敏感信息泄露
strace -e trace=network -s 0 ./program # 不显示数据内容
strace -o /dev/null -c ./program # 只要统计,不要详细日志
10.4 常用组合命令 #
# 网络程序完整分析
strace -f -e trace=network -tt -T -s 256 -o network_trace.log ./network_app
# 文件I/O性能分析
strace -e trace=file -c -S time ./file_app
# 多进程程序调试
strace -ff -o trace_ -e trace=process,network ./multi_process_app
# 实时监控生产程序
strace -p $(pgrep production_app) -e trace=network -c
总结 #
strace 是Linux系统调试和性能分析的强大工具,掌握其使用方法对于:
开发阶段 #
- 理解程序系统调用行为
- 优化I/O操作
- 调试程序异常
运维阶段 #
- 性能瓶颈定位
- 故障原因分析
- 系统行为监控
学习阶段 #
- 理解操作系统原理
- 学习系统编程
- 分析程序运行机制
通过合理使用strace的各种参数和选项,可以深入了解程序的系统级行为,为性能优化和问题排查提供重要依据。
关键要点:
- 选择合适的过滤条件减少噪音
- 使用统计模式进行宏观分析
- 结合时间信息定位性能瓶颈
- 注意生产环境使用的性能影响
- 善用组合参数提高分析效率