登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

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、相对时间或绝对时间,以及前后系统调用的返回值。

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删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>