☰
看清模拟器内部:Baguette logs 实时追踪统一日志与级别/Bundle 过滤完全指南
2026/10/8 13:15:39 网站建设 项目流程

看清模拟器内部:Baguette logs 实时追踪统一日志与级别/Bundle 过滤完全指南

【免费下载链接】baguetteHeadless control for Apple's Simulators — 3D models, taps, swipes, multi-finger gestures, 60 fps streaming, and a multi-device farm项目地址: https://gitcode.com/gh_mirrors/baguette/baguette

做 iOS 开发或自动化时,截图只能告诉你"屏幕现在长什么样",却回答不了"模拟器此刻正在做什么"。Baguette 是一款面向 Apple 模拟器的无头(headless)控制工具,它的baguette logs子命令可以把已启动模拟器的统一日志实时逐行推送到终端,并支持按日志级别、输出风格、NSPredicate 与Bundle ID 过滤——就像给模拟器装了一台"实时监测仪"。

为什么需要模拟器实时日志流 📡

Baguette 的能力矩阵里,screenshot与describe-ui回答的是"此刻",而日志回答的是"过程":

  • 应用生命周期切换、崩溃与异常
  • 系统进程之间的请求与错误
  • 你在自动化脚本里"盲操作"时,模拟器内部的真实反应

过去要手动敲xcrun simctl spawn <udid> log stream才能做到,参数繁琐、难以和自动化流程组合。baguette logs把这件事压缩成一条命令,并且天然支持 shell 管道组合,例如baguette logs --udid X | grep -i error,或者重定向到文件留档。

一键启动:baguette logs 核心用法

安装 Baguette 后(参考仓库 README.md),只要模拟器处于 booted 状态,这条命令就能立即跑起来:

baguette logs --udid <UDID> # 默认 info 及以上、default 风格 baguette logs --udid <UDID> --level debug # 包含 debug 级的一切"碎碎念" baguette logs --udid <UDID> --style json # 每行一个 JSON 对象 baguette logs --udid <UDID> --bundle-id com.apple.MobileSafari baguette logs --udid <UDID> | grep -i error # 与管道自由组合

按 Ctrl-C(SIGINT)即可干净地结束流。全部参数的官方参考见 docs/features/logs/README.md 与 docs/commands.md。

参数速查表

参数默认值作用
--udid必填指定要追踪的模拟器
--levelinfo最低日志级别:default/info/debug
--styledefault输出风格:default/compact/json/syslog/ndjson
--predicate无原样传给log stream --predicate的 NSPredicate
--bundle-id无按进程 Bundle/镜像名过滤,等价于process == "<id>"

这些选项在 LogsCommand.swift 中定义,取值范围直接读取自领域层,保证 help 文案和实际解析逻辑永不漂移。

级别过滤:只有 default / info / debug 三档

很多从 macOS 宿主log工具迁过来的同学会发现:宿主端支持的notice、error、fault在这里统统不接受⚠️

原因很具体:模拟器 iOS 运行时里打包的log程序是"瘦身版",只认三档级别,每档的语义都是"包含该严重度及以上的事件"——所以default一档其实已经覆盖了 default / error / fault。Baguette 选择在入口处直接拒绝非法级别(快速失败),而不是把参数透传下去等系统报错。级别解析逻辑见 LogFilter.swift。

💡 想只看错误?用 predicate:--predicate 'messageType == "error"',这是官方推荐的"按严重度过滤"姿势。

Bundle 过滤:精准锁定一个应用

--bundle-id是最高频的便捷参数。它会被翻译成 NSPredicate 中的process == "<id>";如果你同时给了--predicate,两者会用 AND 组合,翻译与转义逻辑都在 LogFilter.swift 里(连com.acme."weird"这类带引号的怪 ID 都已转义处理)。

典型场景——排查双击手势时官方示例(来自 docs/features/double-tap/README.md):

baguette logs --udid "$UDID" \ --predicate 'process == "SpringBoard" OR process == "<your-app>"'

NSPredicate 高级过滤与输出风格

--predicate是原样透传的"逃生舱",能按 subsystem、category、事件名等任意维度裁剪日志流:

baguette logs --udid <UDID> --predicate 'subsystem == "com.apple.UIKit"'

而--style json/--style ndjson会让每一行都是一个完整 JSON 文档,方便你的脚本二次解析、入库或喂给 AI 分析——这对写自动化断言("日志里是否出现过某事件")特别顺手。

serve 模式:通过 WebSocket 订阅实时日志流

如果你在跑baguette serve起多设备农场,日志同样可以走 WebSocket——每个消费者一条独立 socket:

WS /simulators/<UDID>/logs?level=info&style=compact WS /simulators/<UDID>/logs?bundleId=com.apple.MobileSafari

服务端帧结构极简:连接先发{"type":"log_started"},之后每行日志发{"type":"log","line":"…"},结束时发{"type":"log_stopped"};想提前结束就发{"type":"stop"}。注意两个设计约束:

  • 过滤条件在连接时固定,想换过滤就重连(便宜且无歧义)
  • 慢客户端最多落后 2048 行,再落后会静默丢弃旧行(保留最新),暂无log_dropped提示

协议细节见 docs/features/logs/README.md。

幕后机制:为什么要借道 simctl

设计文档里有一条耐人寻味的"坑"(docs/features/logs/design.md):直接调用 CoreSimulator 的SimDevice.spawn启动log stream看似几乎可行,但会在模拟器内报Must be admin to run 'stream' command——因为 Apple 只对simctl这类官方签名进程授予特权 bootstrap 上下文。Baguette 因此选择xcrun simctl spawn <udid> log stream …借道执行,稳定且零额外依赖。

数据通路上还有两个小角色,都做到了纯值类型、可单测:

  • LineBuffer.swift:把原始字节流按\n切行,残缺的半行留到下一块再拼,坏 UTF-8 行直接跳过而不是中断整个流
  • LogBatcher.swift:面向浏览器端按"200 行或 50ms"成批打包,把每秒几百行的日志量压到约 20 帧/秒,避免打满前端主线程

常见坑位清单 ⚠️

  1. --level只有三档:notice/error/fault会被拒绝,按严重度过滤请用 predicate
  2. 只有实时流:没有历史log show查询,回放磁盘日志请直接xcrun simctl spawn <udid> log show …
  3. 一条流一个过滤器:改过滤 = 重连/重跑命令
  4. 别指望慢消费者不丢行:WebSocket 落后 2048 行开始静默截断

相关文档与源码

资源路径
功能速览与示例docs/features/logs/README.md
设计决策(为何借道 simctl、线程模型)docs/features/logs/design.md
CLI 命令实现Sources/Baguette/App/Commands/LogsCommand.swift
过滤条件与 argv 生成Sources/Baguette/Domain/Logs/LogFilter.swift
流生命周期协议Sources/Baguette/Domain/Logs/LogStream.swift
子进程封装Sources/Baguette/Domain/Logs/Subprocess.swift
全量命令参考docs/commands.md

一条baguette logs,让模拟器的"内心活动"第一次变得可见、可过滤、可断言——调试自动化脚本、观察系统行为、甚至训练 AI 分析日志,从此都有了干净的数据源。

【免费下载链接】baguetteHeadless control for Apple's Simulators — 3D models, taps, swipes, multi-finger gestures, 60 fps streaming, and a multi-device farm项目地址: https://gitcode.com/gh_mirrors/baguette/baguette

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询