strace的常用案例
这是面向初学者与日常运维/开发的 strace 学习说明与操作案例,覆盖安装、核心概念、常用选项、典型问题的排查步骤与解读方法。
一、strace 是什么
- 作用:跟踪进程的系统调用(syscall)与信号,展示每个调用的参数、返回值、耗时等,用于定位“程序和内核交互”层面的问题(文件、网络、权限、进程、内存、时间、线程同步等)。
- 适用场景:
- 程序“卡住/变慢”在哪里?
- 为什么报 No such file or directory / Permission denied?
- 进程在访问哪些文件/网络?
- 动态库/配置文件加载路径问题
- 注意事项:
- 对被跟踪进程有一定性能影响(尤其是大量 I/O 时),生产环境请谨慎。
- 需要足够权限(对别的进程常需 root 或设置 ptrace 权限)。
- 某些安全策略(如 Yama ptrace_scope、容器安全设置)会限制附加。
二、安装与基本用法
- 安装:
- Debian/Ubuntu: sudo apt-get install strace
- CentOS/RHEL: sudo yum install strace 或 dnf install strace
- Alpine: apk add strace
- 基本运行:
- 新启动并跟踪:strace
- 附加到已有进程:sudo strace -p
- 输出到文件:strace -o trace.log
三、常用选项速览
- 跟踪范围
- -e trace= 只跟踪某类或某些 syscall,如:
- -e trace=file 关注文件相关(openat/stat/access 等)
- -e trace=network 关注网络(socket/connect/sendto/recvfrom 等)
- -e trace=process/fault/signal/ipc 等
- -e trace=openat,stat,access 精确到单个/多个 syscall
- -P
仅追踪命中该路径的文件操作(内核新一点的 strace 支持)
- -e trace= 只跟踪某类或某些 syscall,如:
- 进程/线程
- -p 附加
- -f 跟踪子进程/线程(fork/vfork/clone)
- -ff 配合 -o file 使用,按 PID 分文件输出 file.
- 输出控制与细节
- -o 写文件
- -s 增加字符串截断长度(默认 32),如 -s 200
- -v 更详细地打印结构体/标志位
- -y 打印文件描述符对应的路径
- -yy 打印套接字/文件描述符的“解码信息”(如协议、目标)
- -k 打印内核调用栈(需要内核支持,调试符号)
- 时间与统计
- -tt/-ttt 打印时间戳(微秒/Unix 时间)
- -T 打印每个 syscall 耗时
- -c 统计模式:结束时输出各 syscall 次数、耗时占比、失败率
- 高级与实验
- -e inject=… 可做错误注入/延迟(版本需较新,慎用)
- -D 将跟踪工作放入子进程,降低对被跟踪程序干扰
四、快速上手练习(由浅入深)
练习 1:观察一个命令读取了哪些文件
- 目的:理解 openat/stat/access 等调用与路径搜索
- 命令:
- strace -o trace.log -e trace=file -s 200 ls /tmp
- 关注点:
- 动态库加载:openat(…, “/lib/x86_64-linux-gnu/…”, O_RDONLY|O_CLOEXEC) = fd
- 配置/本地文件:openat(AT_FDCWD, “/etc/ld.so.cache”, O_RDONLY|…) …
- 找不到文件返回:ENOENT (No such file or directory)
练习 2:只看网络连接与 DNS 查询
- 命令:
- strace -e trace=network -s 200 curl http://example.com
- 搭配:
- strace -e trace=file,network -s 200 curl http://example.com
- 解读:
- socket(AF_INET/AF_INET6, …)
- connect(…) = -1 ETIMEDOUT / ECONNREFUSED 代表超时或被拒绝
- 还会看到对 /etc/resolv.conf、/etc/hosts 的读取(DNS 配置)
练习 3:统计程序花费时间在哪些系统调用
- 命令:
- strace -c your_program
- 输出解读(示例):
- read/write/futex 比例很高 → I/O 瓶颈或锁争用
- clock_gettime 开销大 → 频繁获取时间
- 如果有大量失败率高的调用(如 ENOENT 的 stat)可能是路径探测过多
练习 4:跟踪子进程与更丰富输出
- 命令:
- strace -f -o trace.log -s 200 -yy -tt -T your_program
- 说明:
- -f 跟踪子进程/线程,-yy 解码 FD/套接字,-tt 打印时间戳,-T 打印耗时
- 大程序/服务建议使用 -ff -o trace 让每个 PID 打到 trace.
练习 5:附加到卡住的进程看看在等什么
- 命令:
- sudo strace -p -s 200 -tt -T
- 常见卡点:
- futex(…, FUTEX_WAIT, …) 长时间不返回 → 线程锁等待
- read(…, fd=0/管道/套接字) 阻塞 → 上游没写数据
- connect/send/recv 阻塞 → 网络不通/对端无响应
- openat/stat 反复访问同一文件 → 配置或路径问题
五、典型问题排查案例
案例 1:程序报 No such file or directory,但文件明明在
- 现象:./app 报错:No such file or directory
- 排查步骤:
- strace -e trace=file -s 200 ./app
- 关注最后失败的 openat/execve 行
- 若 execve(“./app”, …) = -1 ENOENT,可能是架构/动态链接器问题(如缺少 /lib64/ld-linux-x86-64.so.2),不是当前目录没有该文件
- 若 openat(AT_FDCWD, “config.yaml”, …) = -1 ENOENT,说明相对路径问题,程序工作目录不对
- 解决:
- 使用绝对路径或调整工作目录
- 检查 ldd ./app 动态库是否缺失;安装所需库或设置 LD_LIBRARY_PATH
案例 2:命令行工具启动很慢
- 现象:启动数秒后才输出
- 操作:
- strace -tt -T -e trace=file,network -s 200 cmd
- 观察:
- 对 /etc/hosts、/etc/resolv.conf、~/.config 等大量 stat/open 操作是否失败且反复
- connect 到某地址耗时很长(connect(…) = -1 ETIMEDOUT <5.000000>)
- 解决:
- 修正 DNS/网络配置或禁用不必要的网络探测
- 减少无效路径探测(配置缓存)
案例 3:Web 服务偶发 5xx,怀疑文件句柄耗尽
- 操作:
- sudo strace -p -s 200 -tt -T -e trace=file
- 观察:
- openat 频繁成功但 close 极少 → FD 泄漏
- 使用 -y 可把 fd 对应路径打印出来,定位未关闭的文件或 socket
- 进一步:
- lsof -p 查看句柄数量;修复代码路径加 close()
案例 4:容器内网络不通
- 操作:
- strace -e trace=network -yy curl http://service:8080
- 观察:
- connect(fd=3<socket:[…], AF_INET 10.0.0.5:8080) = -1 EACCES/ENETUNREACH
- 方向:
- 容器网络策略、iptables、主机防火墙、DNS 解析
案例 5:多进程程序分叉行为
- 操作:
- strace -ff -o trace -s 200 -f server
- 观察:
- trace. 中寻找 fork/clone/execve 调用链,定位是哪个子进程出错
六、输出阅读技巧
- 基本格式:
- syscall(arg1, arg2, …) = return_value errno
- errno 如 ENOENT/EPERM/EACCES/EAGAIN 提示原因
- 常见文件相关 syscall:
- openat/stat/access/read/write/close/getdents64
- 常见网络相关 syscall:
- socket/connect/bind/listen/accept/sendto/recvfrom/setsockopt/getaddrinfo 期间的文件读取
- 字符串截断:
- 看到 “…” 说明被截断,使用 -s 200 或更大
- 时间定位:
- 用 -tt 和 -T 快速找到耗时调用
七、权限与环境注意
- 需要能 ptrace 目标进程:
- echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope(临时放宽,谨慎)
- 或以 root 身份运行
- setuid 程序可能受限制;容器中需 CAP_SYS_PTRACE 等能力
- 32/64 位混合环境可能显示不同的调用名称(如 open vs openat)
八、常用小抄
- 跟踪文件调用并保存:
- strace -e trace=file -s 200 -o file.log
- 跟踪网络:
- strace -e trace=network -yy
- 统计耗时:
- strace -c
- 附加到卡住的进程:
- sudo strace -p -s 200 -tt -T
- 跟踪子进程并分文件:
- strace -ff -o trace -f
九、进一步学习
- man strace 查看全量选项与示例
- 结合 ltrace(跟踪库调用)、perf/ftrace/bpf 工具形成多层排障组合
- 在测试环境演练错误注入:-e inject=connect:error=ECONNREFUSED:when=3