-e trace=file 是最简路径,只捕获 open、read、write、stat 等文件相关系统调用;必须配合 -f 覆盖子进程,避免遗漏关键操作;结合 -tt 和 -t 可定位时间点与耗时瓶颈,但需警惕 -t 自身开销。

只跟踪文件操作:-e trace=file 是最简路径
想快速确认程序是否在读写某个配置、日志或临时文件,-e trace=file 是最直接的过滤方式。它只捕获与文件系统相关的系统调用,比如 open、openat、read、write、close、stat、unlink、mkdir 等,大幅减少干扰信息。
注意:-e trace=file 不等于只抓 open 和 read —— 它是内建的预设集合,行为由 strace 源码定义,不同版本可能略有出入(如较新内核下会包含 openat,老版本可能不包含)。别试图用 -e trace=open,read,write 手动拼凑来替代,容易漏掉关键调用(比如 stat 判断文件是否存在)。
实际运行时必须加 -f 才能覆盖子进程的文件操作
很多程序会 fork 出子进程执行实际任务(比如 nginx worker、Java 应用的子线程对应内核线程、shell 脚本调用的命令),如果只跑 strace -e trace=file cmd,你只会看到主进程的少量初始化动作,真正干活的子进程调用全被忽略。
-
-f是必需项,不是可选项;不加就等于只看了个开头 - 若需把每个进程输出分开到独立文件,用
-ff -o trace.log,结果会生成trace.log.1234、trace.log.1235等,其中 1234 是 PID - 避免用
-F:它已废弃,且在-f存在时无额外作用
输出里怎么识别真实失败和“预期中的失败”
-e trace=file 输出中频繁出现 -1 ENOENT (No such file or directory) 或 -1 EACCES (Permission denied) 很正常,不代表程序出错——很多程序会试探性打开多个路径(如 /etc/myapp.conf → /usr/local/etc/myapp.conf → $HOME/.myapp.conf),靠失败来决定最终加载哪个。
真正值得关注的是:
- 同一路径反复
open失败(比如每秒十几次open("/tmp/lock", ...)返回-1 ENOENT),可能是轮询逻辑失控 -
write返回值远小于请求长度(如write(3, "hello", 5) = 0),说明文件描述符卡住或被关闭 - 大量
stat+open组合但始终不read,可能是配置热重载机制在空转
配合 -tt 和 -T 才能看出文件 I/O 的真实瓶颈
光看调用列表只能知道“做了什么”,看不出“为什么慢”。加 -tt 可定位时间点,加 -T 才暴露耗时大户:
示例输出:15:23:42.123456 open("/var/log/app.log", O_WRONLY|O_APPEND|O_CREAT, 0644) = 3
这里 是该次 open 耗时(单位秒),而前面的时间戳能帮你对齐其他日志或监控指标。常见陷阱:
-
-T本身有开销,高频率调用下(如每秒数千次write)会让 strace 自身成为性能瓶颈,此时应改用-c做统计而非逐条计时 -
-tt和-T可共存,但不要加-r(相对时间戳)——它和-tt混用会导致时间列错位,难以对齐 - 若目标程序本身对延迟敏感(如实时音视频服务),
strace的介入可能掩盖或放大问题,此时应优先考虑perf trace -e 'syscalls:sys_enter_openat'这类低开销替代方案
真正难的不是加参数,而是从一堆 open、stat、read 中分辨出哪一行是“程序以为自己在读配置”,哪一行是“其实正在疯狂刷日志到 NFS 挂载点导致超时”。这需要你提前了解程序的行为模式,而不是依赖 strace 告诉你答案。











