Tips & Tricks (更新: 2026/6/3)

Claude Code 生产事故指南:检测、回滚、RCA 与预防

Claude Code 生产事故实战指南:密钥泄露、误删、数据库、成本、回滚、RCA 与预防。

Claude Code 生产事故指南:检测、回滚、RCA 与预防

Claude Code 能读取文件、修改代码并执行命令,所以在生产仓库里非常快。速度本身不是问题,问题是一次含糊的批准也可能泄露密钥、删除文件、覆盖 main、执行危险迁移,或让 API 调用失控。

本文不是某家公司的真实事故报告,而是 ClaudeCodeLab 在演练、仓库审查和内容运营中整理出的合成案例。时间和金额只是示例,但事故形态适合在真正出事前练习。

事故指影响用户、数据、安全、成本或可用性的事件。封锁是先阻止损害继续扩大。RCA 是根因分析。回滚是回到最后一个安全版本。

具体配置请以官方 Claude Code settingshooks guide 为准。本文把它们组织成一条流程:检测、封锁、诊断、回滚、沟通、复盘、预防复发。

响应流程

阶段目标可以让 Claude Code 做什么
检测确认变更和影响范围汇总告警、日志、diff、部署和最近命令
封锁阻止损害扩大提出吊销密钥、暂停任务、关闭 feature flag 或禁用接口
诊断缩小直接原因对比最后的正常部署和可疑变更
回滚回到安全状态列出目标版本、数据风险和验证命令
沟通降低不确定性起草状态、影响、下次更新时间和负责人
复盘把事故变成学习填写 RCA、时间线、检测遗漏和行动项
预防降低复发概率增加权限、hooks、CI、告警和审查关卡

涉及密钥、账单、个人数据和数据库写入时,先封锁,再调查。

七种具体事故模式

模式会发生什么第一动作常见失败
密钥泄露.env、日志或截图暴露 API key吊销、轮换、检查日志清理 git,却忘记 CI 日志
危险删除rm -rf 删除必要文件停止操作、查备份、列出未跟踪文件git checkout . 无法恢复未跟踪文件
force pushmain 覆盖团队提交停止 push、查 reflog、建恢复分支混淆 --force-with-lease--force
数据库迁移drop、全表更新或锁表导致故障暂停写入、保存状态、规划恢复未测试 SQL 直接进生产
API 无限重试失败越多调用越多,成本上升杀进程、暂停队列、检查限额“重试”变成无限循环
依赖部署失败本地通过,生产启动 503激活上一版部署、检查 lockfilenpm update 意外升级 major
缺少认证管理接口公开禁用接口、查访问日志、必要时通知只写“admin”,没有写认证要求

三个演练案例

密钥泄露通常来自 GitHub secret scanning、云告警或账单页面。第一步是吊销密钥,不是继续查原因。之后再检查公开仓库、PR、CI 日志、聊天记录和监控。

git status --short
git diff --cached --name-only
git log --all -- .env .env.local
git grep -n "sk-" -- ':!node_modules' ':!dist'

数据库迁移失败时,先暂停写入。代码可以快速回滚,但删除的数据需要备份、WAL、审计日志或外部系统重新同步。

psql "$DATABASE_URL" -c "select now();"
psql "$DATABASE_URL" -c "\d users"
pg_dump "$DATABASE_URL" --schema-only > schema_before_repair.sql

API 重试必须有硬上限。把下面保存为 incident-budget-runner.mjs,用它包住批处理。

#!/usr/bin/env node
import { spawn } from "node:child_process";

const command = process.argv.slice(2);
const maxAttempts = Number(process.env.MAX_ATTEMPTS || 3);
const maxCostCents = Number(process.env.MAX_COST_CENTS || 200);
const costPerAttempt = Number(process.env.COST_PER_ATTEMPT_CENTS || 0);

if (command.length === 0) {
  console.error("用法: node incident-budget-runner.mjs <命令> [...参数]");
  process.exit(2);
}

let estimatedCost = 0;

for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
  const child = spawn(command[0], command.slice(1), {
    stdio: "inherit",
    shell: process.platform === "win32"
  });
  const exitCode = await new Promise((resolve) => {
    child.on("exit", (code) => resolve(code ?? 1));
  });
  estimatedCost += costPerAttempt;
  if (exitCode === 0) process.exit(0);
  if (estimatedCost >= maxCostCents) {
    console.error(`已停止: 预估成本达到 ${estimatedCost} 美分`);
    process.exit(1);
  }
  const delayMs = Math.min(1000 * 2 ** (attempt - 1), 10_000);
  await new Promise((resolve) => setTimeout(resolve, delayMs));
}

console.error(`失败: 已尝试 ${maxAttempts} 次`);
process.exit(1);

Claude Code 防护栏

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(git push --force *main*)",
      "Bash(git push -f *main*)",
      "Bash(rm -rf /*)",
      "Bash(rm -rf ~*)"
    ],
    "ask": [
      "Bash(git push*)",
      "Bash(rm*)",
      "Bash(npm install*)",
      "Bash(*migrate*)",
      "Bash(*deploy*)"
    ]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-danger.sh"
          }
        ]
      }
    ]
  }
}
#!/usr/bin/env bash
set -euo pipefail

payload="$(cat)"
command="$(node -e 'const fs = require("fs"); const raw = fs.readFileSync(0, "utf8") || "{}"; const json = JSON.parse(raw); console.log(json.tool_input?.command || "");' <<< "$payload")"
blocked='(rm[[:space:]]+-rf[[:space:]]+(/|~)|git[[:space:]]+push[[:space:]].*(-f|--force)([[:space:]]|$)|DROP[[:space:]]+TABLE|TRUNCATE[[:space:]])'

if [[ "$command" =~ $blocked ]]; then
  echo "已阻止危险命令: $command" >&2
  exit 2
fi

exit 0

沟通和复盘模板

## 事故更新
- 状态: 调查中 / 已封锁 / 正在验证恢复
- 影响: 功能、用户、开始时间
- 当前动作: 已停止任务、已回滚部署、正在查看日志
- 下次更新: YYYY-MM-DD HH:mm
- 负责人:
# 复盘: [标题]

## 摘要
- 开始:
- 检测:
- 恢复:
- 影响:
- 严重级别: P0/P1/P2/P3

## 时间线
| 时间 | 事件 |
| --- | --- |
| HH:mm | |

## 原因
- 直接原因:
- 根因:
- 为什么检测晚了:

## 预防
| 行动 | 负责人 | 截止日期 |
| --- | --- | --- |
| | | |

外部参考可以阅读 Google SRE 的 Postmortem Culture

封锁完成后,不要急着让 Claude Code “顺手修好全部”。先把证据冻结下来:部署版本、相关 PR、告警截图、日志查询、执行过的命令、受影响用户范围和已经采取的封锁动作。然后把修复拆成三类:立即恢复服务的动作、当天必须补上的检测动作、下一个迭代再做的结构性预防。这样做的好处是,Claude Code 可以分别生成回滚 PR、告警规则和复盘行动项,而不是把临时补丁、长期重构和沟通文案混在一次巨大修改里。团队复盘时也能看清楚,事故是权限太宽、验证不足、自动化缺少预算,还是人工批准点放错了位置。

相关阅读和 CTA

继续阅读 Claude Code 安全最佳实践权限设置指南API 成本指南验证记录流程

个人使用可先下载免费速查表。需要可复用模板时,查看 ClaudeCodeLab 产品。团队要整理 CLAUDE.md、权限、hooks、审查和事故演练,可以看 Claude Code 培训与咨询

在 ClaudeCodeLab 的演练中,最有效的改变是先写封锁步骤,再写诊断步骤。发布前验证 JSON、Bash 和 Node 代码的语法,也减少了简单错误。一次 20 分钟演练通常就能暴露缺少告警、备份未验证、Claude Code 权限过宽这些问题。

#claude-code #incident #production #sre #security #postmortem
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。