跑 WebCraftBench 卡在半途,通常不是单一原因:一类是渲染依赖没装齐,浏览器进程起不来或页面一直白屏;一类是单任务超时被设得太短,任务还没渲染完就被判超时;还有一类是整批任务的超时预算不够,跑到中途整批被终止。先别急着调大超时,用退出码和最后几行日志把问题落到具体阶段,再决定是补依赖还是改超时。
建议固定一个判断顺序:记录退出码 → 看最后几行日志 → 检查有无中间产物 → 用最小脚本单独调起浏览器。退出码非 0 且日志停在启动阶段,多为依赖或浏览器路径问题;日志停在渲染阶段且没有截图、快照类产物,通常是超时太短或页面未就绪;日志停在评分阶段,则更可能是评分脚本读不到产物。日志不完整时不要下结论,先把日志落盘再复现一次。
先看退出码和最后一行输出,确定卡在哪个阶段
先把退出码、日志尾部、产物目录三样一起收齐,再判断是哪一类问题。通常可以在运行命令后立刻执行下面几行,把现场留下来:
bench run ... ; echo "exit=$?"
tail -n 50 run.log
ls -l out/ artifacts/ 2>/dev/null三类问题的典型表现可以这样区分:
- 启动失败:日志很早结束,退出码非 0,常见提示是找不到浏览器可执行文件、缺少系统库、沙箱权限不足。此时产物目录一般是空的。
- 渲染卡住:日志能走到打开页面或等待某个选择器,但最后一行长时间不动,退出码可能是超时导致的非 0,产物目录没有截图或 DOM 快照。
- 评分中断:渲染产物已经生成,日志进入评分环节后报错,往往是产物缺失、路径不对或格式不符合评分脚本预期。
如果日志被截断、只有一行超时提示,先不要判断是依赖问题还是超时问题,把日志级别调高、把标准输出和错误输出都重定向到文件,再复现一次更可靠。
用最小脚本验证渲染环境能否被调起
绕开基准本身的调度和评分,单独确认浏览器与依赖可用。下面是一个打开简单页面并截图的最小示例,放在项目根目录执行,具体引入的库以你环境里实际安装的为准:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.setContent('<h1>probe ok</h1>');
await page.screenshot({ path: 'probe.png' });
await browser.close();
console.log('probe done');
})().catch(e => {
console.error('probe failed:', e.message);
process.exit(1);
});成功与失败的判断方式:能打印 probe done,并且 probe.png 生成且体积不为 0,说明浏览器可以被调起、页面可以渲染。若在 launch 阶段就报错,通常是浏览器二进制缺失或系统库不全;若截图文件没有生成,则要看是否需要调整无头模式、沙箱参数或显式指定浏览器路径。跨机器跑时,最好把浏览器安装位置也一并确认。
核对单任务超时与整体超时两组配置
超时通常至少有两层:单条任务的超时和整批运行的超时。前者管一条任务渲染加评分是否跑得完,后者管整个套件是否在预算内结束。下面只是配置层级的骨架,配置项名称以你实际使用的配置为准:
# 名称以实际配置为准,仅示意层级关系
task_timeout_ms = 120000
suite_timeout_ms = 3600000
retry = 0
headless = true判断方向是:如果失败集中在少数任务、日志显示渲染还没结束就被切断,先看单任务超时;如果任务大多是成功的,但跑到中途整批被终止,则更可能是整体超时或外层调度器的限制。可以把超时先放大一轮,观察是否仍然失败——仍然失败就说明不是时间不够,而要回到依赖、页面就绪条件或产物路径上排查。放大超时只是缩小问题范围的临时手段,不建议作为长期方案,否则会掩盖真正的卡点。
用一条最小任务跑通端到端再做全量
把规模压到一条任务,确认输入、渲染、评分三段都能走通,再放开任务数量。单条任务的命令骨架大致如下,参数名按你的工具替换:
bench run `--suite` webcraft `--task` <task_id> \
`--out` ./out/single `--log` ./out/single/run.log三段验证点分别是:
- 输入:日志里能看到任务文件、页面资源或配置被正确加载,没有报路径不存在。
- 渲染:产物目录出现截图、DOM 快照或渲染结果文件,且文件不是空的。
- 评分:评分结果文件写出,里面能看到该任务的得分字段或错误字段,而不是只有一段异常堆栈。
三段都通过后再逐步扩大任务数量,比如先跑同一个小分组,再跑全量。这样即使后面出错,也能判断是环境问题还是某类任务本身的问题。
把环境信息固化进运行记录
同一个报错下次再出现时,最容易忘的就是“环境是不是变了”。建议每次运行都把环境信息落到产物目录旁边,和日志放在一起,比如 out/run-meta.yaml 或 out/run.env。记录内容至少包含:
runtime: node 或 python 的主版本号
browser: 浏览器名称与版本
system: 操作系统与关键系统库
依赖: package-lock.json 或 requirements.txt 的提交号、哈希
task_timeout_ms: 本次取值
suite_timeout_ms: 本次取值
cmd: 实际执行的完整命令
log: 日志文件位置版本和依赖清单可以用 node -v、npm ls `--depth`=0、pip freeze 之类的命令导出后追加进记录文件。存放位置建议跟随运行产物或按日期分目录,并纳入版本管理或归档,避免下次只有一条报错、没有可比对的基线。记录本身不需要复杂格式,能回答“这次和上次差在哪”就够用。