当前位置:首页 > 文章列表 > 文章 > linux > strace -f 跟踪多进程子调用的输出整理

strace -f 跟踪多进程子调用的输出整理

来源:17golang原创 2026-11-13 19:18:25 0浏览 收藏

多进程程序排查时,单独执行 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、相对时间或绝对时间,以及前后系统调用的返回值。

strace -f 从父进程扩展到子进程并写入带 PID 日志的静态结构图
图1:结构说明图,展示父进程、子进程、-f 跟踪范围与单文件日志之间的静态关系,不是终端截图或运行证据。

先过滤调用类别,再整理真正相关的行

多进程程序的系统调用数量很容易超过人工阅读范围。-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,并保留原始分文件作为回溯材料。

strace 过滤类别、按 PID 分文件并交给脚本消费的静态关系图
图2:数据流说明图,展示调用过滤、单文件或 PID 分文件、脚本消费和异常边界,不代表某台机器的实际输出。

退出和异常行要单独处理

跟踪日志里的返回值是排查结果的一部分。看到 = -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 深挖时再拆分。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
/proc/self/fd 读取进程已打开文件的排查方法/proc/self/fd 读取进程已打开文件的排查方法
上一篇
/proc/self/fd 读取进程已打开文件的排查方法
CSS :is() 合并选择器并保持可读性的设计
下一篇
CSS :is() 合并选择器并保持可读性的设计
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1015次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1019次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1144次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1119次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    960次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码