- 网络安全
- 开发工具
- 质量保障
【免费下载链接】syzkaller
syzkaller is an unsupervised coverage-guided kernel fuzzer
导读
本文讲解 syzkaller 仓库中专门用于导出 AI/Agentic 工作流(workflow)运行数据的工具:Aflow Data Extraction Tool。该工具从 syzbot 仪表盘(Dashboard)暴露的 JSON API 拉取 AI 任务列表与完整执行轨迹(trajectory),并将结果以结构化目录形式落盘,供离线分析与优化使用。读完本文,你将掌握:Dashboard 侧json=1接口的设计与实现位置、tools/extract_workflows.sh脚本的完整参数与执行流程、输出目录结构,以及如何基于源码证据扩展这套抽取能力。
背景:为什么要抽取 Workflow 数据
syzkaller 在 pkg/aflow 中实现了一套 Agentic 工作流执行引擎,支持流程(flow)、动作(action)、Agent、工具(tool)等多层执行语义,并依赖 LLM 完成诸如崩溃复现(repro)、代码审查等任务。这些工作流运行在 syzbot 云端仪表盘上,每次运行都会产生一条完整的执行轨迹:调用了哪些工具、各阶段输入输出、耗时与错误信息等。
这些数据对离线分析和优化极具价值:可以统计各工作流的成功率、定位 LLM 调用失败环节、对比不同代码版本(commit)下工作流行为的变化。而 Aflow Data Extraction Tool 正是为此设计——它不依赖数据库直连,而是通过 Dashboard 对外暴露的 JSON 接口获取数据,天然与仪表盘页面上看到的内容保持一致。
Dashboard 集成:json=1查询参数
要支持数据抽取,syzbot 仪表盘在 AI 任务相关页面上增加了json=1查询参数支持,共两个端点:
- AI 任务列表:
/{ns}/ai?json=1返回该命名空间(namespace)下所有 AI 任务的 JSON 列表,包含工作流类型、状态、代码修订版本(code revision)等元数据; - AI 任务详情:
/ai_job?id=<id>&json=1返回指定任务的详细信息,包括完整执行轨迹(由 flow、action、agent、tool 执行的 span 组成)。
这两个端点复用现有的writeJSONVersionOf辅助函数,把内部页面数据结构直接序列化为 JSON。
源码实现位置
从源码看,这两处实现位于 dashboard/app/ai.go:
- 任务列表页处理函数
handleAIJobsPage在r.FormValue("json") == "1"时,将组装好的uiAIJobsPage页面结构通过writeJSONVersionOf(w, page)以 JSON 形式写出(ai.go#L406-L409); - 任务详情页则通过
handleAIJobPageJSON处理json=1与export=1两个参数:json=1时返回uiAIJobDetails{Job, Trajectory, Args}结构(ai.go#L838-L861)。
writeJSONVersionOf定义在 dashboard/app/main.go#L1689-L1696:
func writeJSONVersionOf(writer http.ResponseWriter, page any) error { data, err := GetJSONDescrFor(page) if err != nil { return err } _, err = writer.Write(data) return err }它调用GetJSONDescrFor将任意页面结构转换为 JSON 描述,再写入响应。列表页返回的核心结构uiAIJobsPage定义于 dashboard/app/ai.go#L37-L51,包含Jobs(任务切片)、Workflows(可用工作流名称)、Managers(可用 manager 列表)以及分页游标字段;任务详情结构uiAIJobDetails则定义于 ai.go#L223-L227,包含任务本体、轨迹 span 列表与参数列表。
任务 JSON 字段说明
uiAIJob结构(dashboard/app/ai.go#L255-L275)定义了单个任务序列化后的字段,抽取脚本直接依赖其中几个:
| JSON 字段 | 类型 | 含义 |
|---|---|---|
ID | string | 任务唯一 ID,也是详情接口的入参 |
Workflow | string | 工作流类型名称(如repro、repro-c) |
Created | time | 任务创建时间(RFC3339 字符串) |
Finished | time | 任务完成时间;零值(0001-01-01T00:00:00Z)表示尚未结束 |
CodeRevision | string | 任务运行的 syzkaller 代码修订(commit) |
AgentName | string | 执行的 Agent 名称 |
Error/ErrorSummary | string | 任务错误信息与摘要 |
Correct | string | 正确性标记(用于 review 流程) |
Results | []*uiAIResult | 结构化执行结果 |
详情接口返回的Trajectory是[]*aflowhtml.UIAITrajectorySpan切片,其中的每个 span 对应一次 flow/action/agent/tool 执行记录,是离线分析的核心数据。
抽取脚本:tools/extract_workflows.sh
抽取过程由 bash 脚本自动化完成,脚本位于 tools/extract_workflows.sh。脚本使用set -e,任何一步失败都会立即退出,便于在 CI 或批处理任务中安全使用。
用法
./tools/extract_workflows.sh <dashboard_url> <commit> [output_dir]参数说明:
dashboard_url:AI 任务列表页 URL,例如http://localhost:8080/linux/ai;commit:一个 syzkaller commit 哈希。脚本只抽取在该 commit当天或之后(按日期比较)运行的工作流,除非任务的CodeRevision与该 commit 完全一致(这种情况即使更早也会被纳入);output_dir:可选,抽取数据的存储目录,默认extracted_workflows。
脚本对参数的校验逻辑(extract_workflows.sh#L11-L18):URL与COMMIT缺失时打印用法并exit 1;OUTPUT_DIR为空时回退为extracted_workflows。
认证支持
脚本支持通过环境变量ACCESS_TOKEN携带 Bearer Token:
CURL_OPTS=(-s -A "") if [ -n "$ACCESS_TOKEN" ]; then CURL_OPTS+=(-H "Authorization: Bearer $ACCESS_TOKEN") fi也就是说,curl统一使用静默模式(-s)并携带空 User-Agent(-A "");当访问需要登录的仪表盘时,先导出ACCESS_TOKEN环境变量,脚本会自动附加Authorization: Bearer $ACCESS_TOKEN请求头。
执行流程
脚本共分五步:
- 获取 commit 日期:通过
git log -1 --format=%ct "$COMMIT"取得指定 commit 的时间戳(Unix 秒); - 拉取任务列表:调用列表端点并附加
json=1。脚本会智能处理 URL 是否已含查询参数——已含?时追加&json=1,否则追加?json=1(extract_workflows.sh#L28-L35); - 过滤:用
jq将列表解析为 TSV(ID、Workflow、Created、CodeRevision 四列),先剔除Finished为零值(即未完成任务)的行,再逐行判断:任务创建时间早于 commit 时间且CodeRevision与目标 commit 不一致的任务被跳过; - 拉取详情:从原始 URL 中提取协议与主机(
grep -oE '^https?://[^/]+')得到BASE_URL,对每个命中任务调用/ai_job?id=${ID}&json=1获取完整轨迹; - 存储:按工作流类型创建子目录,将详情 JSON 保存为
<job_id>.json。
过滤与下载的核心循环(extract_workflows.sh#L43-L66)如下:
printf "%s\n" "$DATA" | jq -r '.Jobs[] | select(.Finished != "0001-01-01T00:00:00Z") | "\(.ID)\t\(.Workflow)\t\(.Created)\t\(.CodeRevision)"' | while IFS=$'\t' read -r ID WORKFLOW CREATED REVISION; do if [ -z "$ID" ] || [ "$ID" == "null" ]; then continue fi # Convert created time to timestamp JOB_DATE=$(date -d "$CREATED" +%s) # Filter by date or exact commit match if [ "$JOB_DATE" -lt "$COMMIT_DATE" ] && [ "$REVISION" != "$COMMIT" ]; then continue fi echo "Fetching details for job $ID..." DETAIL_URL="${BASE_URL}/ai_job?id=${ID}&json=1" TARGET_DIR="${OUTPUT_DIR}/${WORKFLOW}" mkdir -p "$TARGET_DIR" FILE_PATH="${TARGET_DIR}/${ID}.json" curl "${CURL_OPTS[@]}" "$DETAIL_URL" > "$FILE_PATH" done几点实现细节值得注意:
Finished零值判断"0001-01-01T00:00:00Z"与 Go 中time.Time的零值序列化格式一致——未完成任务在 JSON 中就是该字符串,这保证了脚本只抽取已结束的工作流;- 日期比较使用
date -d "$CREATED" +%s,要求运行环境支持 GNU date 语义; - 任务 ID 为空或为字面量
"null"时跳过,防御异常数据; - 每个命中任务独立请求详情接口,天然支持断点式增量抽取(已下载的任务可通过目录内文件判断跳过)。
输出结构
抽取结果按工作流类型分目录组织:
output_dir/ ├── repro/ │ ├── 12345678-1234-5678-1234-567812345678.json │ └── ... ├── repro-c/ │ ├── ... └── ...每个 JSON 文件是一次工作流运行的完整快照,包含任务元数据(Job)、完整执行轨迹(Trajectory)与任务参数(Args),可供其他分析工具直接消费。
数据的可消费性:与轨迹渲染层的对应
抽取出的Trajectory与仪表盘详情页实际渲染的轨迹是同一份数据。Dashboard 使用 pkg/aflow/trajectory 下的aflowhtml.RenderTrajectory将 span 渲染为 HTML(dashboard/app/ai.go#L810),而 JSON 模式输出的uiAIJobDetails.Trajectory字段同样是[]*aflowhtml.UIAITrajectorySpan。这意味着离线 JSON 与线上页面看到的信息完全一致,分析脚本可以直接解析 JSON 而不需要 HTML 解析。
测试验证:接口行为已被用例锁定
Dashboard 对这两个 JSON 端点有完整的端到端测试覆盖,见 dashboard/app/ai_test.go:
- 创建任务后,通过
c.GET(fmt.Sprintf("/ai_job?id=%v&json=1", resp.ID))验证响应包含"Trajectory"字段(ai_test.go#L443-L445); - 同时验证
export=1端点返回dashapi.AIJobPollResp结构(ai_test.go#L448-L453); - 在管理员与普通用户两种权限下均验证了
/ai_job?id=...&json=1的可用性(ai_test.go#L1543-L1548); - 任务列表页的
?json=1输出也在测试中被调用验证(ai_test.go#L539)。
这些用例保证了 JSON 接口的字段结构稳定,抽取脚本所依赖的.Jobs[]、.Finished、.Created、.CodeRevision等字段不会在 Dashboard 演进中无声变化。
实操指南:完整跑通一次抽取
假设你有一个本地运行的 syzbot Dashboard(或线上实例),并按以下步骤操作:
- 确认端点可用:先用浏览器或 curl 验证
http://localhost:8080/linux/ai?json=1返回 JSON 数组;再挑一个任务 ID 验证http://localhost:8080/ai_job?id=<id>&json=1; - 确定基线 commit:进入仓库执行
git log,选定一个你关心的 commit 哈希作为抽取基线; - (可选)配置认证:若 Dashboard 需要登录,先
export ACCESS_TOKEN=<your-token>; - 运行脚本:
./tools/extract_workflows.sh http://localhost:8080/linux/ai <commit_hash> ./wf_data脚本运行过程中会打印Fetching job list from $URL...、Processing jobs...、Fetching details for job <ID>...与最终的Extraction complete.提示;
- 检查结果:
wf_data/下应出现按工作流类型命名的子目录,每个子目录内是<job_id>.json文件。
进阶用法
- 按工作流类型定向抽取:Dashboard 列表页支持
workflow查询参数(对应handleAIJobsPage中的r.FormValue("workflow"),见 dashboard/app/ai.go#L295),可在dashboard_url后追加&workflow=repro只拉取某类工作流,减少数据量; - 增量更新:重复运行脚本并指定同一
output_dir,已存在的 JSON 文件会被覆盖更新,可配合更严格的日期过滤实现增量同步; - 离线分析:对每个 JSON 文件中的
Trajectoryspan 做统计(如按 span 类型、时长、错误率聚合),或结合Args字段还原任务的输入参数。
局限与注意事项
- 脚本依赖
jq、curl、GNUdate,运行环境需预装这些工具; - 日期过滤是"创建时间 >= commit 时间 或 CodeRevision 完全匹配",并非精确的提交祖先关系判断;若任务代码版本恰好早于基线但已包含目标改动,可能会被过滤掉,需要自行权衡;
- 抽取的是 Dashboard 页面视图的数据快照,不包含数据库中的全部原始字段(如内部评论、补丁版本历史等);
CodeRevision匹配是精确字符串比较,commit 缩写形式不会命中,建议使用完整 40 位哈希。
总结
Aflow Data Extraction Tool 通过仪表盘的json=1接口与 tools/extract_workflows.sh 脚本,为 syzkaller 的 Agentic 工作流提供了轻量、可脚本化的离线数据管道。它复用了页面渲染同源的数据结构(uiAIJobsPage/uiAIJobDetails),由writeJSONVersionOf统一序列化,配合 dashboard/app/ai_test.go 的端到端测试保证接口稳定。对于想要分析工作流成功率、定位 LLM 调用失败、对比不同代码版本行为差异的开发者来说,这是一条开箱即用的数据通道。
- 网络安全
- 开发工具
- 质量保障
【免费下载链接】syzkaller
syzkaller is an unsupervised coverage-guided kernel fuzzer
相关推荐
syzkaller Dashboard 部署指南:基于 App Engine 的 syzbot 前端
syzkaller Dashboard 部署指南:基于 App Engine 的 syzbot 前端 dashboard 是 syzkaller 项目中支撑 s
网络安全开发工具质量保障NeoForge模组兼容性指南:解决90%的常见冲突问题
NeoForge模组兼容性指南:解决90%的常见冲突问题 NeoForge作为基于Forge的Minecraft模组开发API,为玩家提供了丰富的模组扩展功能。
granite-timeseries-patchtst高级教程:如何基于预训练模型微调自定义时间序列数据
granite timeseries patchtst高级教程:如何基于预训练模型微调自定义时间序列数据 granite timeseries patchtst
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考