strace 系统调用跟踪
strace 是 Linux 的系统调用追踪工具,可以看到程序在底层到底调用了哪些操作系统功能。白话说就是"给程序装个监控摄像头,看它在后台偷偷做了什么"。
核心知识点
| 概念 | 说明 |
|---|
| 系统调用(syscall) | 程序请求操作系统干活(打开文件、读写、网络等) |
| strace | 追踪程序的系统调用和信号 |
| open/openat | 打开文件的系统调用 |
| read/write | 读写数据的系统调用 |
| connect/socket | 网络连接的系统调用 |
| execve | 执行新程序的系统调用 |
| 信号(signal) | 进程间通信的机制(如 SIGKILL、SIGTERM) |
安装配置
# Ubuntu/Debian 安装
sudo apt install strace # 安装 strace
# CentOS/RHEL 安装
sudo yum install strace # 安装 strace
# 确认安装
strace --version # 查看版本
基本使用
追踪命令
# 追踪一个命令的所有系统调用
strace ls /tmp # 看 ls 命令在底层做了什么
# 输出会显示每个系统调用、参数和返回值
# 追踪并只显示特定类型的系统调用
strace -e open ls /tmp # 只看打开文件的调用
strace -e read,write ls /tmp # 只看读写操作
strace -e network ls /tmp # 只看网络相关的调用
# 追踪子进程(程序启动的其他进程也一起追踪)
strace -f bash -c "echo hello" # -f 跟踪子进程
# 显示调用耗时
strace -T ls /tmp # -T 在每行后面显示这个调用花了多长时间
# 显示时间戳
strace -t ls /tmp # 显示时间(秒)
strace -tt ls /tmp # 显示时间(微秒)
strace -ttt ls /tmp # 显示 Unix 时间戳
追踪正在运行的进程
# 追踪正在运行的进程(需要 root 或相同用户)
sudo strace -p 12345 # 12345 是进程 PID
# 先找到进程 PID
pidof nginx # 查看 nginx 的 PID
pgrep -f "python app.py" # 查找 python 进程的 PID
# 追踪并且不中断进程
sudo strace -p $(pidof nginx) -e read,write # 只看 nginx 的读写操作
# 追踪多线程程序
sudo strace -fp $(pidof nginx) # -f 同时追踪所有线程
高级用法
按类型过滤系统调用
# 只看文件相关操作
strace -e trace=file ls # 所有文件相关:open、stat、unlink 等
# 只看网络相关操作
strace -e trace=network curl example.com # socket、connect、send 等
# 只看进程管理
strace -e trace=process bash -c "ls" # fork、exec、wait 等
# 只看内存操作
strace -e trace=memory ls # mmap、brk 等
# 只看信号
strace -e trace=signal ls # 信号相关
# 组合多种类型
strace -e trace=file,network curl example.com # 文件 + 网络
统计分析
# 统计系统调用次数和耗时(非常实用)
strace -c ls /tmp # -c 显示统计摘要
# 输出类似:
# % time seconds calls errors syscall
# 25.00 0.001 10 2 openat
# 15.00 0.000 20 0 read
# ...
# 统计 + 详细输出
strace -C ls /tmp # -C 既显示详细又显示统计
# 排序统计结果
strace -c -S time ls /tmp # 按时间排序
strace -c -S calls ls /tmp # 按调用次数排序
输出到文件
# 输出到文件(不影响终端)
strace -o trace.log ls /tmp # -o 输出到文件
# 追踪多进程时每个进程一个文件
strace -ff -o trace.log bash -c "ls; date"
# 会生成 trace.log.PID1, trace.log.PID2...
# 追加模式
strace -o trace.log -p 12345 # 追踪运行中的进程并保存
实用排查场景
# 场景1:程序找不到文件
strace -e openat python app.py 2>&1 | grep "No such file"
# 看程序在哪些路径下找文件,找不到的会显示 ENOENT
# 场景2:程序启动慢,找出瓶颈
strace -c -S time python app.py # 统计哪个调用最耗时
# 场景3:程序连不上数据库
strace -e connect python app.py 2>&1 | grep -i "connect"
# 看连接的 IP 和端口对不对
# 场景4:查看程序读了哪些配置文件
strace -e openat nginx -t 2>&1 | grep ".conf"
# 看 nginx 测试时读了哪些配置文件
# 场景5:程序卡住了(hang),看在等什么
sudo strace -p $(pidof myapp) # 看它卡在哪个系统调用上
# 如果卡在 read/poll/select,说明在等待 IO
# 如果卡在 futex,说明在等锁
# 场景6:看程序的环境变量
strace -e trace=read -s 1000 env 2>&1 | head -20
# -s 1000 显示更长的字符串
过滤文件描述符
# 只看特定文件描述符的读写
strace -e read=3 -e write=3 ls # 只看文件描述符 3 的读写
# 显示完整的字符串内容(默认截断 32 字符)
strace -s 500 cat /etc/hosts # -s 500 显示前 500 个字符
strace -s 0 cat /etc/hosts # -s 0 不限长度,显示全部
常见报错
| 问题 | 原因 | 解决 |
|---|
attach: Operation not permitted | 没有权限追踪其他用户的进程 | 加 sudo 或修改 ptrace_scope |
| 输出太多看不过来 | 没有过滤 | 用 -e trace=file 等过滤 |
| 字符串被截断 | 默认只显示 32 字符 | 加 -s 500 或 -s 0 |
| 追踪导致程序变慢 | strace 有性能开销 | 用 -c 统计模式减少开销 |
No such process | PID 不存在或已退出 | 先 ps 确认进程还在 |
速查表
# === 基础追踪 ===
strace 命令 # 追踪命令
strace -p PID # 追踪运行中的进程
strace -f 命令 # 连子进程一起追踪
strace -o 文件 命令 # 输出到文件
# === 过滤 ===
strace -e trace=file 命令 # 只看文件操作
strace -e trace=network 命令 # 只看网络操作
strace -e trace=process 命令 # 只看进程操作
strace -e openat,read 命令 # 只看特定调用
# === 显示控制 ===
strace -s 500 命令 # 字符串显示 500 字符
strace -T 命令 # 显示每个调用耗时
strace -t/-tt 命令 # 显示时间戳
# === 统计 ===
strace -c 命令 # 统计摘要
strace -C 命令 # 详细 + 统计
strace -c -S time 命令 # 按耗时排序
# === 常见组合 ===
strace -e openat 命令 2>&1 | grep "No such file" # 找缺失文件
strace -e connect 命令 2>&1 | grep connect # 看网络连接
strace -c -S time 命令 # 性能瓶颈分析
sudo strace -p PID -e trace=file # 看进程文件操作