外观
第 10 章 · 常见问题与排障
再好用的工具也会出问题:连不上、答非所问、弹窗不停、界面卡住。新手与高手面对异常的差别是——新手慌乱乱试,高手有一套稳定的诊断路径。本章把高频问题按类讲透,并给出官方提供的排障命令与定位思路。
本章包含 5 个知识点:
- 排障总思路:先判断问题出在哪一层
- 网络与鉴权问题:连不上、报权限、被限流
- 模型与上下文问题:答得差、突然变笨、窗口爆了
- 权限、工具与 MCP 问题:弹窗异常、操作被拦、服务器连不上
- 日志、性能剖析与问题上报
知识点 1:排障总思路:先判断问题出在哪一层
① 定位
遇到任何异常,第一步都不是「试解决方案」,而是「判断问题出在哪一层」。方向错了,后面所有操作都是浪费。本知识点建立排障的总坐标系。
② 是什么(What)
OpenCode 采用客户端—服务器(client-server)架构:一个后台服务拥有会话、插件、权限等应用状态;TUI 只是连接它的客户端。因此所有问题首先归入三类:
text
① 客户端问题(TUI 显示、按键、主题异常)
② 共享服务器问题(服务卡死、状态异常、所有项目都受影响)
③ 特定项目问题(只在某仓库出现:配置、规则、MCP)官方提供的第一组诊断命令:
bash
opencode service status # 当前后台服务信息
opencode api get /api/info # 验证服务 API 是否健康
opencode service restart # 服务卡死 / 不健康时重启
opencode service stop # 也可显式停止
opencode service start # 再启动正常情况下 OpenCode 会自动发现 / 启动后台服务,这些命令只在诊断其生命周期时才需要。
③ 怎么做(How)
- 先问:这问题只在一个项目出现,还是所有项目都有?(全有 → 偏向服务 / 全局;只一个 → 项目配置层)
- 跑
opencode service status和opencode api get /api/info看服务是否健康; - 服务异常 →
service restart,再复现问题; - 怀疑界面问题 → 重启 TUI(客户端)而不是动服务;
- 一个容易被忽视的技巧:直接让 OpenCode 排查它自己——描述问题并让它参考官方 Troubleshooting 页面、检查服务与日志。
④ 为什么这么做(Why)
- 分层架构决定了必须分层排障。 客户端负责渲染、服务端负责状态;把客户端的显示问题归因到服务、或把服务卡死归因到某个项目,都会做无用功。先定位层级,是效率的分水岭。
- 「所有项目 vs 单个项目」是成本极低、信息量极大的测试。 换个目录启动一次,问题是否复现立刻把范围缩小一半——这是排障中最划算的实验。
- 服务有独立生命周期,所以需要显式诊断命令。 服务可能在你关闭 TUI 后仍常驻;重启 TUI 并不能重启它。理解这点才能解释「重启界面没用」。
- 先诊断、后行动,避免破坏性操作。 在没搞清问题前删除配置、重置数据库可能造成不可恢复的损失;官方明确警告不要直接编辑服务文件与数据库。
- 让 AI 自我排查利用了它的工具能力。 它可以读日志、查服务状态、按官方步骤核对——这正是第 9 章工作流在「元层面」的应用。
⑤ 这样做的好处
- 排查不绕路,几步内锁定层级。
- 解决方案与问题层级匹配:重启该重启的东西。
- 不破坏数据:诊断优先于重置。
- 复现路径清晰,便于求助和上报。
- 心态稳:有坐标系就不慌乱。
⑥ 不这么做的问题 / 坏处
- 不分类就乱试 → 重装、删配置、重置一通,问题没解决还可能丢数据。
- 只重启 TUI → 服务仍在卡死状态,毫无效果。
- 直接编辑 / 删除服务文件和数据库 → 可能造成不可恢复的损坏。
- 不做对照实验 → 无法判断是项目问题还是全局问题。
⑦ 举一反三:三个例子
例 1(基础):界面显示错乱
📌 场景:TUI 花屏、按键无响应,但其它终端正常。
✅ 判断与动作:先归为客户端层——退出并重启 TUI;若恢复即无需动服务。
🔍 讲解:渲染问题最廉价的修复是重启客户端。先试成本最低、与层级匹配的动作,不要上来就重启整个服务。
例 2(进阶):所有项目都无法正常对话
📌 场景:换任何目录都卡住、报错。
✅ 顺序:opencode service status → opencode api get /api/info;不健康则 service restart,再验证。
🔍 讲解:跨项目复现把问题指向共享服务;一条 restart 往往解决卡死与状态错乱。
例 3(挑战):只在某个项目出怪问题
📌 场景:同一个 TUI、同一个服务,仅某仓库里 AI 行为异常。
✅ 排查:检查该项目的 opencode.jsonc / .opencode/ 配置、AGENTS.md、项目级 MCP;可临时把这些移走做对照——若恢复正常,逐项加回定位元凶。
🔍 讲解:项目特有问题的元凶几乎总在项目配置层。**对照实验(移走可疑文件 → 复现 → 逐项加回)**是定位配置类问题的通用方法。
⑧ 练习题 ×2
练习 1(巩固型)
📝 题目:OpenCode 的问题首先分哪三类?写出检查后台服务健康和重启服务的命令。
💡 思路提示:客户端 / 服务器 / 项目;service status、api get、restart。
✅ 参考答案:
text
三类:客户端(TUI)问题、共享服务器问题、特定项目问题。
命令:
opencode service status
opencode api get /api/info
opencode service restart(也可 service stop / start)🔍 讲解:这是排障的第一层心智模型,遇到异常先在脑中过一遍。
练习 2(迁移型)
📝 题目:迁移到就医流程:好医生为什么先判断「问题在哪个系统」(分诊),而不是病人一说疼就开药?「所有场合都疼 vs 只在某动作时疼」这类信息对诊断有何价值?
💡 思路提示:先定位、对照信息缩小范围。
✅ 参考答案(示例):
text
- 分诊先确定病灶系统,避免头痛医头、用错治疗;
- 「什么情况下出现 / 不出现」是极高价值的对照信息,
能迅速缩小病因范围;
- 共性:排障也讲究「先分层定位、用最小对照实验缩小范围、
再对症下药」,而不是一上来就尝试各种解决方案。知识点 2:网络与鉴权问题:连不上、报权限、被限流
① 定位
最高频的一类故障:TUI 能开,但消息发不出去、报 401/403、或频繁限流。这类问题都发生在「OpenCode → 供应商 API」的链路上,第 8 章的网络配置是其直接武器。
② 是什么(What)
常见报错与对应根因:
| 现象 | 典型根因 |
|---|---|
| TLS / 连接错误、所有 HTTPS 打不开 | 网络 / 代理节点故障(本书写作期间就亲历:某代理节点 HTTP 通、HTTPS 全被掐断) |
| 401 / 鉴权失败 | API Key 无效或过期、凭证未正确注入 |
| 403 / 无权限 | 凭证有效,但账号未开通该模型 |
| 429 / rate-limit | 请求过快或额度受限 |
| 证书错误 | 处于私有 CA / TLS 拦截环境,信任链缺失 |
对应配置手段(第 8 章):代理三件套(HTTP_PROXY / HTTPS_PROXY / NO_PROXY 含回环)、服务环境持久化(opencode service set env)、私有 CA 走 NODE_EXTRA_CA_CERTS。
③ 怎么做(How)
- 先区分「网络层」还是「鉴权层」:
curl一个简单站点(如https://www.gstatic.com/generate_204)看网络通不通; - 网络通但报 401 → 检查 API Key 是否有效、过期,重新登录 / 更新环境变量;
- 报 403 → 到供应商控制台确认目标模型已开通 / 激活;
- 遇 429 → 放慢节奏、等一会再试;有多供应商 / 多模型时临时切换;
- 代理环境下优先怀疑节点:切换一个节点(不同地区)再试,是验证节点故障最快的方法。
④ 为什么这么做(Why)
- 网络与鉴权是链路上先后两道关,必须分开验证。 网络不通时,再正确的 Key 也发不出去;网络通而 Key 错,换节点也无济于事。按顺序排除,避免在错误的关卡上使劲。
- 一个最小的网络探针胜过反复猜测。
curl一个 generate_204 地址,几秒就能判断「是全网问题还是模型 API 问题」——这是网络排障的标准起手式。 - 401 与 403 的区分对应「身份」与「权限」。 401 = 你是谁无法验证(凭证);403 = 知道你是谁、但你不能做这个(模型未开通)。理解语义才能一步定位。
- 429 是供给方的保护机制而非错误配置。 突发请求触发限流时,继续重试只会加重;放慢节奏、切换渠道才是正解。
- 代理节点是「不可见的第三方」,故障形式多样。 本书亲历的案例(HTTP 正常、HTTPS 被掐)说明:不要因为「能上网」就断定节点没问题;换节点对照是最可靠的验证。
- 证书问题永远补信任、不关校验。 关闭 TLS 验证虽能让请求「看起来成功」,却把通信暴露给中间人。
⑤ 这样做的好处
- 连不上的问题几分钟内定位到具体关卡。
- 凭证、权限、限流各有标准解法。
- 代理故障有快速对照手段。
- 保持安全姿态:不因排障关闭安全机制。
- 求助时能提供清晰的错误信息。
⑥ 不这么做的问题 / 坏处
- 不分网络 / 鉴权就乱改 → 时间全花在无关处。
- 401 就去开通模型、403 却去换 Key → 动作与根因错位。
- 429 后疯狂重试 → 限流时间更长,甚至触发更严保护。
- 为通过证书错误而关闭 TLS 校验 → 安全彻底失守。
⑦ 举一反三:三个例子
例 1(基础):突然所有网站都打不开
📌 场景:浏览器、curl 的 HTTPS 全部 TLS EOF。
✅ 动作:先用 HTTP 站点 / 代理管理 API 确认是节点问题;切换到另一地区节点后恢复(真实案例:日本节点坏、德国节点正常)。
🔍 讲解:全网 HTTPS 同时失败,优先怀疑代理链路而非单个网站或本机配置。换节点是验证 + 解决一步完成。
例 2(进阶):登录成功却报模型无权限
📌 场景:凭证有效,发消息却返回 403。
✅ 动作:到供应商控制台检查该模型是否已在你的账号下开通 / 激活,开通后重试。
🔍 讲解:这是经典的「身份通过、授权未过」。分清 401/403,就不会徒劳地反复换 Key。
例 3(挑战):间歇性 429 的综合治理
📌 场景:长会话中频繁触发限流,影响节奏。
✅ 组合手段:放慢请求节奏、把琐碎任务合并后一次提交、配置第二供应商 / 模型作为限流时的退路;联网搜索场景利用多供应商的自动 429 切换(第 7 章)。
🔍 讲解:限流治理是「降速 + 冗余」组合拳,而不是与限流机制对抗。
⑧ 练习题 ×2
练习 1(巩固型)
📝 题目:401 与 403 分别表示什么?遇到 429 正确的应对是什么?
💡 思路提示:凭证 vs 模型权限;放慢、等待、切换。
✅ 参考答案:
text
401:鉴权失败——API Key 无效 / 过期(身份无法验证)。
403:无权限——凭证有效,但账号未开通该模型。
429:被限流——放慢节奏、等待冷却,或切换供应商 / 模型;
不要疯狂重试。🔍 讲解:记住三个状态码的语义,网络类问题的定位速度会快一个量级。
练习 2(迁移型)
📝 题目:迁移到快递物流:「地址错误(找不到收件人)」「收件人拒收(无权限)」「仓库爆仓需排队(限流)」三类状态,与 API 的 401/403/429 如何对应?快递公司靠什么手段应对爆仓?
💡 思路提示:身份 / 授权 / 容量;分流与等待。
✅ 参考答案(示例):
text
- 地址错误、找不到收件人 ≈ 401(身份 / 凭证问题);
- 收件人明确拒收 ≈ 403(身份明确但无权限);
- 爆仓排队 ≈ 429(容量受限,非错误);
- 应对爆仓:换分拨中心(≈ 换供应商)、错峰发货
(≈ 放慢节奏)、等待恢复。
共性:网络 API 的错误语义与物流状态同构——
先读懂状态含义,再选分流 / 等待 / 补凭证的对策。知识点 3:模型与上下文问题:答得差、突然变笨、窗口爆了
① 定位
另一大类「软性故障」:没有明显报错,但 AI 表现不对劲——答非所问、忘记前文、质量下滑。这类问题没有错误码可查,必须从模型与上下文两层找原因。
② 是什么(What)
常见症状与根因对照:
| 症状 | 可能根因 |
|---|---|
| 简单任务也频繁出错 | 当前模型能力不足,或被无意切换到了弱模型(先看状态栏) |
| 忘记前面说过的内容 | 上下文被压缩(compaction 有损)、或相关内容已被挤出窗口 |
| 回答越来越慢、质量下滑 | 上下文过长,窗口接近满载 |
| 明明给过文件却问「这是什么」 | 该文件在很早的位置,压缩后只剩摘要;需重新提供 |
| 答非所问、漏掉约束 | Prompt 本身不清晰(回看第 1 章),或规则冲突 |
③ 怎么做(How)
- 第一反应看状态栏:用的是不是预期的模型?
- 判断是「Prompt 问题」还是「模型能力问题」:任务简单却做不好、且证据齐全 → 切更强模型(
F2); - 怀疑上下文问题 → 手动压缩(
<leader>c),或干脆开新会话、把必需背景精炼后重新提供; - 关键资料被遗忘 → 用
@文件/#行范围重新精确附上,而非口头说「我之前给过」; - 长项目主动分会话(第 2、9 章),不要让一个会话无限延长。
④ 为什么这么做(Why)
- 「突然变笨」最常见的原因是模型被切过。 状态栏一扫即可排除这个变量——成本为零,因此永远排在诊断第一步。
- 压缩是有损的,遗忘是其正常代价。 上下文超预算时,早期细节被摘要替代;模型并非「记性差」,而是信息已物理离开窗口。理解机制就不会期待它记住被压缩掉的原文。
- 软故障必须区分「输入问题」与「能力问题」。 Prompt 含糊时换强模型无用,模型超纲时改写 Prompt 也无用——先分清瓶颈,对策才有效(与第 6 章选型一致)。
- 重开新会话是合理手段而非失败。 一个滚了几千行的会话,上下文信噪比已经很低;带着精炼背景开新会话,质量往往立刻回升。
- 重新提供证据比指责模型有效。 「我之前说过」对模型没有信息量;用
@文件把证据再次放进上下文,才是可执行的纠偏。 - 长会话是质量的慢性毒药。 上下文越长,每轮成本越高、有效信息占比越低;分会话是从源头防护。
⑤ 这样做的好处
- 软故障也有明确的检查顺序,不靠瞎猜。
- 该升级模型时果断、该修 Prompt 时清醒。
- 新会话快速恢复质量。
- 证据补给精准、低成本。
- 长项目质量稳定:上下文始终保持高信噪比。
⑥ 不这么做的问题 / 坏处
- 不看状态栏就怀疑模型「退化」 → 忽略最简单的真相。
- 期待模型记住被压缩的内容 → 反复失望。
- Prompt 含糊却怪模型笨 → 瓶颈判断错误。
- 死守一个超长会话 → 成本高、质量差、还不肯开新的。
⑦ 举一反三:三个例子
例 1(基础):AI「不认识」昨天讨论的方案
📌 场景:长会话压缩后,模型对早期方案细节语焉不详。
✅ 做法:把方案原文(或所在文件 @路径#范围)重新附上,要求它基于原文继续,而不是凭压缩摘要。
🔍 讲解:压缩摘要只保留梗概、丢细节是设计使然。重新注入证据是唯一可靠的补救。
例 2(进阶):简单任务连续出错
📌 场景:一个本该轻松完成的改动,模型反复犯低级错误。
✅ 顺序:看状态栏(是否被切到弱模型)→ 确认后 F2 切回常用模型重做;若模型没问题,回头检查 Prompt 是否缺关键上下文。
🔍 讲解:先排除「模型档位」这个零成本变量,再检查输入——顺序不能反。
例 3(挑战):超长会话的质量急救
📌 场景:会话几千行后,AI 回复变慢、开始遗漏近期约束。
✅ 做法:先手动压缩一次看效果;若仍不理想,开新会话,用一段话精炼交代「项目目标 + 当前进度 + 相关文件 + 下一步」,并用 @文件 附关键证据。
🔍 讲解:新会话 + 精炼背景相当于「上下文重整」。把高信噪比的起点重新建立起来,比在烂上下文里硬聊高效。
⑧ 练习题 ×2
练习 1(巩固型)
📝 题目:AI 忘记前文时,从上下文机制看根因是什么?说出两条正确的补救动作。
💡 思路提示:压缩有损 / 内容被挤出窗口;重新附证据、开新会话。
✅ 参考答案:
text
根因:上下文被压缩(早期细节被摘要替代,属有损操作),
或相关内容已被挤出窗口——不是模型「记性差」。
补救:① 用 @文件 / #行范围 重新精确附上关键证据;
② 或开新会话,精炼背景后重新提供。🔍 讲解:理解「信息物理上是否还在窗口里」,就不会用「请你记住」这类无信息量的话试图修复。
练习 2(迁移型)
📝 题目:迁移到团队的新成员入职:当项目进行到一半换人接手时,为什么「把背景、进度、关键文档重新交接一遍」比让新人「去翻之前所有聊天记录」更高效?这与会话压缩 / 开新会话有何共性?
💡 思路提示:信噪比、精炼交接。
✅ 参考答案(示例):
text
- 全部历史聊天噪音多、关键信息稀释,通读成本高且易漏;
- 精炼的背景 + 当前进度 + 关键文档,信噪比高,上手快;
- 共性:压缩 / 新会话也在做同样的事——丢弃过程噪音、
保留高价值结论,并把关键证据重新明确附上。
上下文管理本质是「让当前工作记忆保持高信噪比」。知识点 4:权限、工具与 MCP 问题:弹窗异常、操作被拦、服务器连不上
① 定位
本类问题表现为:明明想放行却总弹窗、或 AI 突然做不了之前能做的事、MCP 服务器显示连接失败。它们都发生在「工具—权限—外部服务」这一层。
② 是什么(What)
常见症状与根因:
| 症状 | 典型根因 |
|---|---|
| 同一操作反复弹窗 | 没有匹配的 allow 规则;或规则顺序写反(宽规则在最后吞掉例外) |
| 本该拦截的操作被放行 | deny 规则的 resource 没匹配上(模式写错) |
| AI 访问不了工作区外文件 | 缺少 external_directory 授权 |
| MCP 显示未连接 / needs authentication | 远程服务器 OAuth 未登录 |
| MCP 工具调不到 | 服务器被 disabled、配置被同名整体替换、或本地启动命令失败 |
| 自定义 Agent 行为不符预期 | frontmatter 字段(mode/permissions/model)配置有误 |
③ 怎么做(How)
- 弹窗异常 → 检查
permissions规则:顺序是否「宽基调在前、具体例外在后」?resource 模式是否真的匹配? - 用一个最小例子测试规则(如先写一条明确 allow,看弹窗是否消失),逐步定位;
- MCP 连不上 →
opencode mcp list看状态;远程用 TUI/mcps完成登录; - 本地 MCP 失败 → 手动跑一遍它的启动命令,看是否报错(缺依赖、命令不存在);检查
{env:NAME}对应的变量是否已设置; - 配置覆盖问题 → 检查目录树里是否有同名服务器配置整体替换了上级定义。
④ 为什么这么做(Why)
- 权限规则是精确字符串匹配,差一个字符就不生效。 「总弹窗」往往不是系统失灵,而是模式没写对;用最小测试验证匹配,比反复修改猜测快。
- 规则顺序是最常见的人为错误。 「最后匹配生效」意味着宽规则一旦放在末尾,前面的白名单全部失效——这是配置逻辑、不是 bug。
- MCP 故障横跨「网络 / 认证 / 本地进程」三层。 远程看 OAuth,本地看启动命令;
mcp list把状态显式呈现,先看状态再分层排查。 - 同名服务器整体替换的语义可能反直觉。 项目配置不会与上级字段合并;忘记这点会以为「只覆盖了 URL」,实际其它字段全部丢失。
- 最小化测试是定位规则类问题的通用方法。 写一条精确规则、复现一次,立刻知道匹配是否成立——把大问题切成单变量实验。
- 工具不可达时的对策是扩展能力(配规则 / 装 MCP),而非催促模型。 第 7 章已述:Agent 边界由工具决定。
⑤ 这样做的好处
- 弹窗行为如你预期:该自动的自动、该拦的拦。
- MCP 故障分层清晰、定位快。
- 规则改动有测试验证,不靠侥幸。
- 配置覆盖的意外被提前发现。
- 工具能力稳定可控。
⑥ 不这么做的问题 / 坏处
- 弹窗烦就全部 allow → 为便利放弃安全。
- 不验证规则匹配 → 以为配好的 deny 其实形同虚设。
- MCP 失败只反复重启 → 忽略了登录 / 缺依赖等真正根因。
- 忘记整体替换语义 → 上级配置意外丢失,排查无方向。
⑦ 举一反三:三个例子
例 1(基础):git 检查还是弹窗
📌 场景:已写 allow 规则,但 git status 仍每次询问。
✅ 排查:检查规则顺序——若 {shell, *, ask} 写在了 git status allow 之后,宽规则最后生效吞掉例外;把例外移到末尾即可。
🔍 讲解:这是「最后匹配生效」最典型的翻车场景,调整顺序立即解决。
例 2(进阶):远程 MCP 突然不可用
📌 场景:昨天正常的远程 MCP 今天报未连接。
✅ 顺序:opencode mcp list 看是否 needs authentication(token 过期)→ TUI /mcps 重新登录;网络异常则结合知识点 2 排查代理。
🔍 讲解:OAuth token 有有效期;先看显式状态、再做对应层的修复。
例 3(挑战):本地 MCP 启动即失败
📌 场景:本地 MCP 在列表里一直连不上。
✅ 做法:手动执行配置中的启动命令(如 npx -y xxx)直接看报错——常见为命令不存在、缺环境变量、版本不兼容;修复后确认 environment 里的 {env:NAME} 已在启动环境中提供。
🔍 讲解:本地 MCP 本质是 OpenCode 替你拉起的进程;进程本身的问题,把命令拿到外面跑一次立刻水落石出。
⑧ 练习题 ×2
练习 1(巩固型)
📝 题目:已配置 allow 却仍弹窗,说出两个最可能的原因。远程与本地 MCP 连不上时分别优先检查什么?
💡 思路提示:顺序 / 模式;OAuth 登录 / 启动命令。
✅ 参考答案:
text
弹窗原因:① 规则顺序写反,宽泛规则在最后生效;
② resource 模式没真正匹配(字符串 / 通拼写错)。
MCP:远程优先看 mcp list 状态,needs authentication 时
用 /mcps 登录;本地优先手动运行启动命令看报错、
检查环境变量。🔍 讲解:规则看顺序与匹配、MCP 按远程 / 本地分流,是本知识点的全部要点。
练习 2(迁移型)
📝 题目:迁移到门锁 / 门禁系统:「给某人发了门卡却仍刷不开门」,物业排查时为什么先核对「卡的权限范围 / 生效时段 / 门禁是否在线」,而不是直接重发一张卡?这与权限规则、MCP 排障有何共性?
💡 思路提示:单变量核对、分层排查。
✅ 参考答案(示例):
text
- 刷不开可能是权限范围不对(≈ resource 不匹配)、
未到生效时间(≈ 规则顺序 / 条件)、或门锁离线
(≈ 服务器连不上);
- 直接重发卡不定位原因,新卡可能仍失败;
- 共性:排障都应「先看状态、再分层逐变量核对」,
用最小测试确认每一层是否成立,而非盲目重置。知识点 5:日志、性能剖析与问题上报
① 定位
当前述分类都无法解决,或问题涉及卡顿、高内存时,需要进入「深水区」:读日志、抓性能剖析、并在必要时向上游报告。本知识点讲官方提供的可观测性工具与上报规范——这是自助排障的最后一站。
② 是什么(What)
日志:安装版把日志写在:
text
~/.local/share/opencode/log/opencode.log复现问题时可实时跟踪:
bash
tail -f ~/.local/share/opencode/log/opencode.log每行包含进程 run ID 与 role 字段,可按角色(如 server)或某次运行过滤:
bash
grep 'role=server' ~/.local/share/opencode/log/opencode.log
grep 'run=8fc3b1d5' ~/.local/share/opencode/log/opencode.log性能剖析(macOS / Linux):先从健康端点拿后台服务 PID:
bash
opencode api get /api/info然后发信号:
bash
kill -SIGPROF <pid> # 采集 10 秒 CPU 剖析,写入日志目录
kill -SIGUSR1 <pid> # 采集内存堆快照,写入日志目录等日志中出现 CPU profile written / heap snapshot written(含完整路径)后再打开,可用 Chrome DevTools 分析。注意:Windows 不支持;堆快照会短暂暂停进程并增加内存占用。
关键文件位置(不要在排障时直接删除 / 编辑):
text
~/.local/state/opencode/service.json # 服务注册信息
~/.config/opencode/service.json # 私有服务配置
~/.local/share/opencode/opencode.db # 数据库(OPENCODE_DB 可改位置)③ 怎么做(How)
- 复现问题时开一个
tail -f日志窗口,观察报错行; - 用
role/run过滤出相关片段; - 怀疑 CPU / 内存问题(卡顿、风扇狂转、内存持续涨)时,按上述步骤抓剖析文件分析;
- 需要上报时,不直接动数据库,先收集最小复现信息;
- 上报前脱敏:移除 API Key、授权头、Prompt 与文件内容等敏感数据。
④ 为什么这么做(Why)
- 日志是系统的「黑匣子」,记录了界面看不到的内部事件。 会话、供应商、插件、权限、工具活动都有痕迹;当问题无法从外部复现观察时,日志是最直接的证据源。
- 结构化字段(run/role)让大海捞针变得可行。 一次运行可能产生上千行日志;按 run ID 或角色过滤,能迅速锁定与本次故障相关的片段。
- 性能剖析把「感觉卡」变成可分析的事实。 CPU profile 显示时间花在哪里、堆快照显示内存被什么占用——主观体感无法指导优化,剖析数据可以。
- 不直接编辑服务文件 / 数据库,是因为它们是运行时状态。 手工修改极易破坏一致性;官方建议用服务命令管理、外部检查前先备份。
- 上报要求最小复现 + 脱敏,兼顾有效与安全。 维护者需要稳定的复现路径而非泛泛描述;同时日志里常有凭证与隐私,分享前必须清理。
- 先穷尽自助手段、再上报,是对开源协作的尊重,也往往让你在过程中自己找到答案。
⑤ 这样做的好处
- 疑难问题有证据可查,不再只能凭感觉。
- 性能问题能量化、能定位。
- 上报质量高:复现清晰、信息完整,更容易被修复。
- 不泄露敏感数据。
- 不破坏运行时状态。
⑥ 不这么做的问题 / 坏处
- 不看日志就上报 → 描述含糊,问题难以处理。
- 凭感觉判断性能 → 优化错方向。
- 直接删改数据库 / 服务文件 → 可能造成不可恢复的损坏。
- 分享未脱敏日志 → 凭证与隐私泄露。
⑦ 举一反三:三个例子
例 1(基础):用日志定位一次失败调用
📌 场景:某次操作莫名失败,界面只有简短报错。
✅ 做法:tail -f 日志后复现一次,用该次的 run ID 过滤,查看供应商返回的完整错误。
🔍 讲解:界面提示往往是摘要;日志里的完整错误(含供应商原始返回)才是定位根因的关键。
例 2(进阶):抓 CPU 剖析诊断卡顿
📌 场景:服务在某些操作时长时间卡住、CPU 占用高。
✅ 做法:opencode api get /api/info 取 PID → kill -SIGPROF <pid> → 等日志写出文件 → 用 Chrome DevTools 打开分析热点。
🔍 讲解:先量化再优化。剖析会明确告诉你时间消耗在哪个函数,避免猜测。
例 3(挑战):提交一份高质量 Issue
📌 场景:确认是可复现的产品缺陷,需要向官方报告。
✅ 收集清单:
text
1. opencode --version 输出;
2. opencode service status 输出;
3. 最小复现步骤(越少越好);
4. 问题影响范围(服务 / 某客户端 / 某项目);
5. 相关日志片段(保留 run、role 字段);
——全部脱敏后提交到 GitHub Issues。🔍 讲解:复现路径越短、信息越完整,修复越快;脱敏是不可跳过的一步。
⑧ 练习题 ×2
练习 1(巩固型)
📝 题目:日志文件默认写在哪里?过滤日志时最有用的两个字段是什么?抓 CPU 剖析和堆快照分别用什么信号?
💡 思路提示:~/.local/share/opencode/log;run / role;SIGPROF / SIGUSR1。
✅ 参考答案:
text
日志:~/.local/share/opencode/log/opencode.log。
字段:run(某次运行 ID)、role(角色,如 server)。
信号:kill -SIGPROF <pid>(10 秒 CPU 剖析);
kill -SIGUSR1 <pid>(内存堆快照)。🔍 讲解:可观测性命令不常用,但在疑难时刻是破局关键,值得记住入口。
练习 2(迁移型)
📝 题目:迁移到航空事故调查:调查员为什么靠「黑匣子 + 重现事故过程」,而不是只听当事人描述?公开调查报告前为什么要做信息处理?这与日志排障 / Issue 上报有何共性?
💡 思路提示:客观记录、可重现、脱敏公开。
✅ 参考答案(示例):
text
- 当事人记忆主观、不完整;黑匣子客观记录全部飞行数据;
- 用数据重现事故,才能定位真正根因;
- 公开报告需保护当事人隐私、敏感安全信息;
- 共性:日志就是软件的黑匣子——先客观记录、再重现复现、
上报前脱敏。好的排障与好的事故调查遵循同一套方法:
证据优先、最小复现、安全分享。🔍 讲解:这是全书最后一个迁移练习。当你把「证据、复现、脱敏」内化为本能,就不仅能排障 OpenCode,也具备了应对任何复杂技术系统故障的通用素养。
本章小结
| 知识点 | 一句话核心 |
|---|---|
| 1. 排障总思路 | 先分客户端 / 服务 / 项目三层;service status + api 验证,该重启哪层重启哪层 |
| 2. 网络与鉴权 | 401 凭证、403 未开通、429 限流;代理节点用切换对照 |
| 3. 模型与上下文 | 先看状态栏;压缩有损、遗忘正常;新会话 + 重附证据 |
| 4. 权限与 MCP | 弹窗看规则顺序与匹配;远程看 OAuth、本地看启动命令 |
| 5. 日志与上报 | 黑匣子在 log 目录、run/role 过滤;SIGPROF/SIGUSR1 抓剖析;上报最小复现且脱敏 |
结语
排障能力的本质,是在不确定面前保持有条理:先定位、再实验、靠证据决策。结合第 9 章的工作流,你已经拥有了完整的 OpenCode 使用闭环——从写好第一个 Prompt,到系统性交付项目,再到从容处理异常。
至此全部正章完结。建议接下来:① 通读 README.md 的学习路线查漏补缺;② 打开各章练习实际动手做一遍;③ 参考附录中的速查表与推荐资源,把常用信息放在手边。