strace -f 跟踪多进程子调用的输出整理
来源:17golang原创
时间:2026-11-13 19:18:25 185浏览 收藏
多进程程序排查时,单独执行 strace command 只能看到最初进程的系统调用;加上 -f 后,strace 会继续跟踪它通过 fork、vfork 或 clone 创建的子进程。真正容易混淆的地方在于:所有进程的输出默认仍可能交错在同一个流里,读者看到的不是一份天然按业务步骤排好的日志。
本文把输出当作一条数据流来整理:进程树是数据来源,-e trace=... 是筛选,-o 或 -ff 是存储方式,PID 是关联键,退出状态和未完成调用是异常边界。strace 的官方手册地址如下,参数语义以当前手册为准:
官方地址:https://man7.org/linux/man-pages/man1/strace.1.html
需要保留父子调用关系时先用-f -o trace.log;子进程较多、单文件难以阅读时改用-ff -o trace.log,再按生成的 PID 文件逐个分析。
先明确 -f 会把哪些进程纳入跟踪
-f 的作用是跟踪当前已跟踪进程通过 fork(2)、vfork(2) 和 clone(2) 创建出来的子进程。它不是“把机器上的所有进程都抓下来”,也不是按业务名称自动识别进程。跟踪范围从启动命令或附加的 PID 开始,随后沿着进程创建关系扩展。
因此,整理输出时至少要保留两个字段:调用发生在哪个 PID,以及该调用前后对应的进程创建关系。下面的命令用一个会启动子进程的示例脚本作被跟踪对象,-- 后面的内容属于被跟踪命令:
#!/usr/bin/env bash # -f 跟踪脚本创建的子进程;-o 把 strace 输出写入文件 strace -f -o trace.log -- ./worker.sh # 只查看进程生命周期调用,先确认 fork/clone/exec 的关系 strace -f -e trace=process -o process.log -- ./worker.sh
如果只想观察已经运行的服务,可以把起始点换成 -p PID。不过附加到多线程进程时,-f -p PID 还会纳入该进程的线程;不要把线程 ID 和业务上的子进程概念混为一谈。
把多进程输出落到可复盘的单文件
默认情况下,系统调用和信号会写到标准错误。使用 -o trace.log 后,输出改写入指定文件;当 -f 与 -o 同时使用时,strace 会显示 PID 前缀,便于把调用重新归属到进程。
#!/usr/bin/env bash # -tt 记录墙上时间;-T 记录每次系统调用耗时;-s 256 增大字符串展示上限 # -o 让标准输出仍留给被跟踪程序,排查时更容易分别保存业务输出和跟踪输出 strace -f -tt -T -s 256 -o trace.log -- ./worker.sh # 先看父子进程创建和退出的线索,再定位具体文件或网络调用 grep -E 'clone|fork|vfork|execve|exit_group|SIGCHLD' trace.log
单文件适合先建立全局时间线,但它有一个明确边界:父进程和多个子进程的调用会交错写入。交错不等于执行顺序完全错误,真正的关联键应是日志里的 PID、相对时间或绝对时间,以及前后系统调用的返回值。

先过滤调用类别,再整理真正相关的行
多进程程序的系统调用数量很容易超过人工阅读范围。-e trace= 可以使用单个调用名或调用类别;围绕“子进程如何创建、文件从哪里读写、网络连接是否成功”这三类问题,可以分别使用 process、%file 和 %network。
#!/usr/bin/env bash # 只看进程创建、exec 和退出,适合先画出进程生命周期 strace -f -e trace=process -o process.log -- ./worker.sh # 只看文件路径相关调用,适合排查配置文件、权限和路径继承 strace -f -e trace=%file -o file.log -- ./worker.sh # 只看网络相关调用,适合整理 connect、send、recv 等调用 strace -f -e trace=%network -o network.log -- ./worker.sh
过滤会改变你能看到的证据范围:只看 %file 时,无法据此判断进程是不是刚刚由 clone 创建;只看 process 时,也不会告诉你具体哪个配置文件打开失败。先根据问题画出最小证据集合,再决定是否扩大到默认的全部调用。
推荐的整理顺序是:先从 process.log 建立 PID 关系,再在 file.log 或 network.log 中按 PID 查找具体调用,最后回到单文件日志补充时间上下文。这样不会因为日志行数很多就把不同子进程的同名调用合并在一起。
子进程很多时用 -ff 按 PID 拆分日志
当一个父进程会快速创建多个子进程,单文件日志的交错关系会让后续处理变得困难。这时使用 -ff:它组合了 -f 和按进程单独输出的行为。配合 -o trace.log 后,输出文件会带上 PID 后缀,例如 trace.log.1234,具体数字以运行时 PID 为准。
#!/usr/bin/env bash
# -ff 为每个进程建立独立文件;基础名后会附加对应 PID
strace -ff -tt -o trace.log -- ./worker.sh
# 先列出本轮产生的 PID 文件,再逐个查看,不假设 PID 连续
for log in trace.log.*; do
# 文件不存在时保持脚本可读;每个文件对应一个被跟踪进程
[ -f "$log" ] || continue
echo "===== $log ====="
sed -n '1,12p' "$log"
done
-ff 更适合“每个进程分别看什么”的问题,但它不自动生成一条全局时间线,也不能替代 PID 关系图。若需要把分文件结果重新合并成可读的整体视图,可以使用 strace 项目提供的 strace-log-merge,并保留原始分文件作为回溯材料。

退出和异常行要单独处理
跟踪日志里的返回值是排查结果的一部分。看到 = -1 ENOENT、= -1 EACCES 或 unfinished ... resumed 时,应先按 PID 和调用名归档,再判断是路径、权限还是跨线程/跨进程的未完成调用;不要只按字符串出现次数下结论。
#!/usr/bin/env bash # 只抽取失败返回和未完成调用,便于建立异常清单 grep -E '= -1 (ENOENT|EACCES|ECONNREFUSED)|unfinished|resumed' trace.log # 子进程可能在跟踪器退出后仍然存活;需要收尾保护时启用该选项 strace -f --kill-on-exit -o trace-safe.log -- ./worker.sh
--kill-on-exit 会请求在 strace 退出时终止被跟踪进程,适合临时诊断任务不应遗留子进程的场景。它会改变收尾行为,不要对必须继续运行的生产服务随意启用。另一个常见边界是:-c 统计模式与 -ff 的逐进程输出不兼容;需要逐行材料时优先保留普通日志,需要汇总统计时再单独运行统计命令。
一份适合复盘的整理清单
| 问题 | 入口参数 | 整理结果 |
|---|---|---|
| 子进程是否被跟踪 | -f -e trace=process | 得到 fork、clone、exec 和退出关系 |
| 调用发生在哪个进程 | -f -o trace.log | 用 PID 前缀关联父子调用 |
| 只看文件或网络 | -e trace=%file / %network | 缩小阅读范围,但保留过滤边界 |
| 单文件交错太多 | -ff -o trace.log | 按 PID 生成独立日志文件 |
| 诊断结束不留子进程 | --kill-on-exit | 明确这是会改变收尾行为的保护选项 |
最后可以把一次排查的材料固定为“命令行、PID 关系、原始日志、过滤日志、异常清单”五项。命令行记录了筛选边界,原始日志保留上下文,过滤日志服务于阅读,异常清单则把返回值和后续修复动作连接起来。
相关问题
strace -f 和 -ff 有什么区别?
两者都会跟踪子进程;-f 默认把结果放在同一输出流,-ff 还会按进程 PID 拆分输出文件。
为什么日志中会出现多个 PID?
因为 -f 会沿着被跟踪进程创建的 fork、vfork 或 clone 子进程扩展,PID 是区分调用归属的关键字段。
只想看打开文件的调用怎么做?
可以从 strace -f -e trace=%file -o file.log -- command 开始,但要记住它不会提供完整的进程创建时间线。
什么时候不该用 -ff?
当你需要一条快速浏览的全局时间线,或准备使用 -c 做汇总统计时,先使用单文件方式更直接;需要按 PID 深挖时再拆分。
-
369 收藏
-
426 收藏
-
387 收藏
-
242 收藏
-
436 收藏
-
494 收藏
-
287 收藏
-
176 收藏
-
204 收藏
-
307 收藏
-
352 收藏
-
123 收藏
-
240 收藏
-
426 收藏
-
239 收藏
-
358 收藏
-
289 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习