关于 antithesis-debug
antithesis-debug 是用于在 Antithesis 运行或调试会话的指定时刻执行 Bash 脚本的技能。它支持检查运行时状态并调查故障,同时要求使用有效会话和确定的时刻信息。
主要功能
- 01在指定时刻执行 Bash
- 02检查容器和运行时状态
- 03流式查看时间线事件
- 04从运行中提取文件
- 05从同一时刻复现分支
适用场景
- 01调查失败的属性
- 02检查指定时刻的容器
- 03在日志不足时检查运行状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ antithesishq/ antithesis-skills --skill antithesis-debug安装后在 Claude Code 中输入/antithesis-debug确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/errors.mdgdb.mdkubernetes.mdmoments.mdvirtual-time.md详细介绍
Antithesis 调试
技能版本: 2026-10-21 4f8d80b
在运行期间的某个时刻执行 bash 脚本。每次调用都会分支出一个多重宇宙,从同一时刻重复调用会得到相同结果。可以使用当前正在运行的运行实例或活动的 MVD 会话。
何时使用此技能
- 用户向你提供了 Antithesis 调试会话的运行 ID 或 URL
- 用户要求你调试或调查失败的属性、Bug 或过去运行中的任何结果
- 用户要求检查 Antithesis 内的容器文件系统、运行时状态或事件
- 仅凭日志无法解释故障,因此分诊建议使用此技能
属性失败警告
在运行中的实例上使用 runs exec 执行命令可能会触发该运行实例的断言,从而导致属性失败,看起来与真实 Bug 完全相同。
如果想避免此类误报,请使用调试会话。 如果命令不太可能引发此问题,优先使用当前正在运行的实例,因为它速度快、易于使用,并且消耗的核心时数更少。
前提条件
- 如果未安装
snouty,请勿继续。安装选项请参阅https://raw.githubusercontent.com/antithesishq/snouty/refs/heads/main/README.md。 - 如果
snouty版本低于 0.8.0(这是runs exec稳定的首个版本),请勿继续。使用snouty --version查看版本,并使用snouty update更新。 - 必须有来自运行实例或 MVD 会话的会话,才能使用此命令。更多信息请参阅先获取实时会话。
- 必须通过 snouty 登录 Antithesis 租户。运行
snouty doctor进行确认。如果尚未登录,请让用户为你登录,或使用 API 密钥。
先获取实时会话
-
exec需要实时会话。会话可以关联到运行实例或 MVD 会话。在 snouty 中,运行实例和调试会话都显示为运行实例。 -
运行实例在运行期间以及结束后的一小段时间内会保留会话。完成后几分钟内仍可使用,但几小时后就不行了。
-
若要查看运行实例是否有活动会话,请使用:
snouty --json runs show <run> | jq -r '[.status, .sub_status // empty] | join(":") | ascii_downcase'这会同时打印状态和子状态。
in_progress:ready表示可以对运行实例执行命令。若状态为in_progress,但子状态不是ready(例如in_progress:loading),则会话仍在加载。snouty runs wait <run> --until ready会在运行实例就绪可用或已结束时返回。它会打印停止时的状态,因此请确认状态为in_progress:ready后再执行命令。 -
如果用户提供了调试会话 URL,该会话可能已经在运行。请在会话中找到其运行 ID,并根据标题、描述或创建时间进行匹配。
runs list只显示状态,因此请选择一个处于in_progress状态的会话,然后确认runs show显示其状态为in_progress:ready:snouty --json runs list --launcher debugging \ | jq -c '{run_id, status, created_at, title: .parameters["antithesis.test_name"], source_run: .parameters["antithesis.debugging.run_id"]}'source_run是要传递给--source-run-id的值。 -
对于较早的运行实例,请先创建调试会话:
snouty debug --run-id <run> --input-hash <hash> --vtime <vtime> \ --title "Counter property failure 2026-10-13"- 始终传递唯一且便于日后查找的
--title,例如属性名称加日期或工单 ID。这是snouty runs list中显示的会话名称。只有当原因无法放入标题时,才添加--description。--recipients接受以分号分隔的通知邮箱。 - 这会返回一个新运行 ID。使用
snouty runs wait <new run ID> --until ready等待就绪,然后对其执行exec。 - 第一个命令要使用
--source-run-id <run>,因为该时刻尚未预热。使用源运行实例时,调用会阻塞,并显示重新预热进度:N%,直到该时刻就绪。 - 从运行
snouty debug到首次成功执行exec,预计需要 2 到 20 分钟:会话加载期间会出现几分钟的 404,然后时刻重新预热;时刻的 vtime 越晚,重新预热所需时间就越长。此后,该时刻已预热,后续针对该时刻执行的命令无需再指定源运行实例。 - 如果
exec返回 404 或“Moment not warm”,说明会话仍在加载。请重试。查看获取时刻,找到与用户请求相符的正确 input-hash 和 vtime。
- 始终传递唯一且便于日后查找的
获取某个时刻(输入哈希和 vtime)
input-hash 和 vtime 用于固定要调试的单个时刻。从上下文中提取输入哈希和 vtime,并传给命令。
如果用户没有提供时刻,请查看 references/moments.md,了解在哪里查找。
如果无法从明确的来源确定输入哈希和 vtime,请询问用户,不要猜测。
若要从失败或通过的属性,或从日志行中查找时刻(输入哈希 + vtime),请使用 snouty runs search 查询(参见示例工作流的第 3 步)。
必需输入
-
RUN_ID是一个正在运行的 run,或调试会话的 run id。 -
INPUT_HASH和VTIME是该 run 中的一个时刻,必须成对取自snouty runs search返回的同一事件。 -
INPUT_HASH通常为负数,例如-1520695250096255483。请原样传入:snouty 会将其读取为哈希,而不是标志,因此无需添加--。添加--会将其后的所有标志都变成位置参数,从而导致命令出错。snouty runs exec "$RUN_ID" -1520695250096255483 67.7622960046865 'uptime' -
SCRIPT是要运行的 bash 脚本。将其作为最后一个参数传入,或省略该参数并通过管道传入,例如 < script.sh。
可选标志
--timeout DURATION指定服务器等待脚本退出的时长。需要带单位:90s、5m、1h。纯数字表示秒。默认值为 10m(截至版本 64.0)。重新预热冷时刻的时间不计入其中。--container NAME在该容器内运行脚本。若不指定,脚本将在主机上运行。--source-run-id ID指定冷时刻所属的 run。当目标是调试会话时,此处应填写你从中打开该会话的 run,而不是会话 id。启动调试会话后的第一条命令请使用此标志。--source-session-id ID是--source-run-id的会话版本。两者不能同时使用。--events在脚本运行期间流式输出时间线上的每个事件,而不只是脚本的输出。--json输出机器可读的 json 格式。
执行提示
-
在单个容器中运行命令时,优先使用
--container,而不是在脚本内使用 podman exec。 -
--container需要容器名称,且仅适用于 Docker Compose 测试(参见下文的 Kubernetes 测试)。如果已经运行过snouty runs search或snouty runs logs,请从任意容器日志事件的source.container中获取名称。否则,先不带--container运行一次,以便在主机上列出容器:snouty runs exec "$TARGET" "$HASH" "$VTIME" 'podman ps -a --format "{{.Names}} {{.Status}}"'在 Docker Compose 测试中,同一个 run 的所有时刻使用相同的名称,因此只需列出一次。
-
--container仅适用于你所选时刻仍在运行的容器。如果容器此前已崩溃或退出,podman ps -a会将其显示为Exited,此时--container会失败。请从容器仍在运行的较早时刻执行。使用snouty runs search搜索该容器最后几行日志,找到一个时刻。 -
如果需要跨多个容器获取快照,请勿使用
--container,而应在主机上运行。 -
要从 run 中获取文件,请将其打印到标准输出并重定向到本地:
# text snouty runs exec "$TARGET" "$HASH" "$VTIME" --container app 'cat /var/log/app.log' > app.log # binary or a directory: tar + base64, then decode locally snouty runs exec "$TARGET" "$HASH" "$VTIME" --container app \ 'tar czf - /data/db | base64' | base64 -d > db.tgz
Kubernetes 测试
在 Kubernetes 测试中,--container 不起作用(snouty runs show 中的启动器包含 "Kubernetes" 或 "k8s")。请省略该标志,并阅读 references/kubernetes.md。
从文件运行脚本
-
对于超过一行的脚本,请将脚本写入文件,并通过重定向传入:
cat > script.sh <<'EOF' echo "host: $(hostname)" ps aux EOF snouty runs exec "$RUN_ID" "$INPUT_HASH" "$VTIME" < script.sh'EOF'外的引号可避免$(hostname)意外在你的计算机上运行。 -
在多个时刻重复使用同一个脚本。在多个时刻运行同一个文件并比较输出。
-
将输出保存到以该时刻命名的文件中。
-
始终将 --events 输出保存到文件中。输出流很长,因此之后请对文件使用 grep:
snouty runs exec --events $RUN $HASH $VTIME < oracle.sh > out.txt grep -E "FAIL|HIT|exit" out.txt
选择超时值和计时
- 根据脚本本身设置
--timeout。冷时刻会先重新预热,这可能需要几分钟(时刻的 vtime 越靠后,耗时越长),但这段时间不计入--timeout。只有脚本运行缓慢时才提高超时值,例如--timeout 30m。 - 超时不代表脚本没有运行。重新运行任何会改变状态的操作前,先搜索此次运行是否已有输出(
snouty runs search)。 - 脚本会推进虚拟时间。快照应尽量简短。在恰当时刻查询一次,而不是反复轮询,因为轮询可能改变你想要观察的时序。
- 在同一时刻运行相同命令,会得到相同分支。重复运行不会采样新的时序。
- 在会话中,使用 source 成功执行一次命令后,该时刻会保持预热状态。之后在那里运行命令无需 source,且会很快返回。
- 会话自身时间线上的较早时刻也已预热,无需重新预热。
重新预热进度
冷时刻会在重新预热期间显示进度。默认情况下,命令会在 stderr 上输出 rewarming moment: N% 行。使用 --json 时,命令会在 stdout 上输出 {"status":"rewarming","percent_complete":N} 帧,然后才输出脚本结果。
- 百分比上升表示重新预热正在进行。进度上升期间不要重试或取消。
- 百分比可能会在 0% 停留几分钟,然后跳到接近 100%。停留在 0% 并不表示失败。请让调用继续运行。
完成后取消
运行和调试会话在结束前都会占用核心时长。停止使用调试会话并不会结束它:默认情况下,它仅会在 6 小时后过期。打开的会话一旦不再需要,或近期不再需要,就应立即取消:
snouty runs cancel "$TARGET"
- 取消会话前请先询问用户。完成后,他们可能还想在另一次调试中继续使用该会话。
- 取消前,请确认运行或调试会话已彻底完成;如果之后还想运行更多命令,就必须等待新会话完成设置。
- 除非用户要求,否则不要取消并非由你启动的运行。
工作流示例
1. 前置条件
snouty --version # 0.8.0 or newer
2. 获取会话
RUN=<run_id>
snouty --json runs show "$RUN" | jq -r '[.status, .sub_status // empty] | join(":") | ascii_downcase'
-
in_progress:ready:直接使用该运行。TARGET="$RUN"。 -
starting,或处于其他子状态的in_progress:使用snouty runs wait "$RUN" --until ready等待,然后仅在输出的状态为in_progress:ready时使用该运行。 -
否则:选择一个时刻(第 3 步),然后在该时刻打开会话并等待。加载期间,如果 exec 返回 404 或 "Moment not warm",请重试。
snouty debug --run-id "$RUN" --input-hash "$HASH" --vtime "$VTIME" --title "<property> <date>" TARGET=<runId from the output> snouty runs wait "$TARGET" --until ready
3. 选择时刻
使用 snouty runs search 查找时刻,并精确查询你想要的事件。例如,某个属性的失败评估:
snouty --json runs search "$RUN" \
'filter(ev => ev.antithesis_assert?.hit
&& ev.antithesis_assert.id == "<property name>"
&& !ev.antithesis_assert.condition)' \
| jq -r '.moment | "\(.input_hash) \(.vtime)"'
要查找通过的评估,请去掉 !。要查找日志行,请使用 contains({output_text: "<error text>"})。要按消息查找断言,请使用 filter(ev => ev.antithesis_assert?.message?.includes("<message text>"))。断言没有 output_text,因此日志行查询无法找到它们。请参阅 references/moments.md。
runs search 默认最多返回 50 条结果。如果需要的结果不止几条,请添加 --limit 999。
4. 执行
启动会话后执行的第一条命令使用 --source-run-id,因为该时刻仍在预热。之后,该时刻已预热,后续命令无需 source,除非你更改时刻。
cat > probe.sh <<'EOF'
hostname
ps aux | head -20
EOF
snouty runs exec "$TARGET" "$HASH" "$VTIME" --source-run-id "$RUN" < probe.sh > out.txt
5. 使用结果
根据输出完成用户的目标,通常是找出错误原因。如果输出无法回答问题,请在更早的时刻再次执行,或从 end moment 行继续向前。
如有必要,请向用户提供时刻、脚本和相关输出,以便他们重新运行。
6. 取消
如果你打开了会话,运行完命令后请询问用户是否要你取消运行。否则,它会继续占用核心时长,直到 6 小时后过期:
snouty runs cancel "$TARGET"
gdb
要使用 gdb 检查进程,请阅读 references/gdb.md。
虚拟时间
在选择某个时刻或探查瞬时事件之前,请先阅读
references/virtual-time.md。
如果较早的时刻尚未预热,请添加 --source-run-id。
常见错误
如果 exec 返回错误,请阅读 references/errors.md。
自我检查
在反馈之前,请根据以下标准检查你的工作:
- 每项发现都来自实际的
exec输出,而非推断或假设。 - 证据链清晰:时刻(输入哈希和虚拟时间)、脚本、脚本返回的内容,以及由此得出的结论。
- 摘要将输出所显示的内容与解释或建议区分开来。
- 你已询问用户是否要取消你开启的任何调试会话,或者用户知道该会话仍在运行。
已知问题
- 在
snouty runs wait --until ready返回后,exec仍可能在几分钟内返回 404。请继续重试;会话仍在加载。 - 执行
snouty runs cancel后,运行状态可能显示为completed,而不是cancelled。取消操作已生效。