关于 debugging
面向软件开发者的调试技能,涵盖错误排查、日志分析、性能问题和分布式系统故障。它提供假设驱动的排查流程、结构化分析模板,以及 Python 和 JavaScript/Node.js 调试示例。
主要功能
- 01假设驱动的故障排查
- 02复杂问题的扩展思考指导
- 03MECE、5 Whys 与时间线模板
- 04Python 调试与日志示例
- 05JavaScript/Node.js 调试示例
- 06容器调试指导
适用场景
- 01定位间歇性错误的根因
- 02分析跨服务的分布式故障
- 03排查性能下降或资源问题
- 04使用日志和调试器验证假设
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thelobbi/ claude --skill debugging安装后在 Claude Code 中输入/debugging确认已加载。
详细介绍
调试技能
提供全面的调试能力,并集成扩展思考,适用于复杂场景。
何时使用此技能
在以下情况下启用此技能:
- 错误排查
- 日志分析
- 性能调试
- 分布式系统调试
- 内存和资源问题
- 需要深入推理的复杂、多层级 Bug
复杂调试的扩展思考
何时启用扩展思考
在调试时,遇到以下情况可使用扩展思考(Claude 的深度推理模式):
- 根本原因未知:存在多种可能原因,故障模式不明确
- 间歇性问题:竞争条件、时序问题、非确定性故障
- 多系统故障:涉及多个服务的分布式系统 Bug
- 性能之谜:没有明显瓶颈,却出现意外变慢
- 复杂状态问题:涉及复杂状态转换或副作用的 Bug
- 安全漏洞:需要仔细分析的隐蔽安全问题
如何启用扩展思考
# In your debugging prompt
Claude, please use extended thinking to help debug this issue:
[Describe the problem with symptoms, context, and what you've tried]
扩展思考将提供:
- 系统化的假设生成
- 多路径调查策略
- 更深入的模式识别
- 跨领域洞察(例如,网络 + 应用 + 基础设施)
假设驱动的调试框架
使用以下结构化方法处理复杂 Bug:
1. 观察阶段
What happened?
- Error message/stack trace
- Frequency (always/intermittent)
- When it started
- Environmental context
- Recent changes
2. 生成假设
Generate 3-5 plausible hypotheses:
H1: [Most likely cause based on symptoms]
Evidence for: [...]
Evidence against: [...]
Test: [How to validate/invalidate]
H2: [Alternative explanation]
Evidence for: [...]
Evidence against: [...]
Test: [How to validate/invalidate]
H3: [Edge case or rare scenario]
Evidence for: [...]
Evidence against: [...]
Test: [How to validate/invalidate]
3. 系统化测试
Priority order (high to low confidence):
1. Test H1 → Result: [Pass/Fail/Inconclusive]
2. Test H2 → Result: [Pass/Fail/Inconclusive]
3. Test H3 → Result: [Pass/Fail/Inconclusive]
New evidence discovered:
- [Finding 1]
- [Finding 2]
Revised hypotheses if needed:
- [...]
4. 确定根本原因
Confirmed root cause: [...]
Contributing factors: [...]
Why it wasn't caught earlier: [...]
5. 修复 + 验证
Fix implemented: [...]
Tests added: [...]
Validation: [...]
Prevention: [...]
结构化调试模板
模板 1:MECE Bug 分析(相互独立,完全穷尽)
## Bug: [Title]
### Problem Statement
- **What**: [Precise description]
- **Where**: [System/component]
- **When**: [Conditions/triggers]
- **Impact**: [Severity/scope]
### MECE Hypothesis Tree
**Layer 1: System Boundaries**
- [ ] Frontend issue
- [ ] Backend API issue
- [ ] Database issue
- [ ] Infrastructure/network issue
- [ ] External dependency issue
**Layer 2: Component-Specific** (based on Layer 1 finding)
- [ ] [Sub-component A]
- [ ] [Sub-component B]
- [ ] [Sub-component C]
**Layer 3: Code-Level** (based on Layer 2 finding)
- [ ] Logic error
- [ ] State management
- [ ] Resource handling
- [ ] Configuration
### Investigation Log
| Time | Action | Result | Next Step |
|------|--------|--------|-----------|
| [HH:MM] | [What you tested] | [Finding] | [Decision] |
### Root Cause
[Final determination with evidence]
### Fix
[Solution with rationale]
模板 2:5 个为什么分析
## Issue: [Brief description]
**Symptom**: [Observable problem]
**Why 1**: Why did this happen?
→ [Answer]
**Why 2**: Why did [answer from Why 1] occur?
→ [Answer]
**Why 3**: Why did [answer from Why 2] occur?
→ [Answer]
**Why 4**: Why did [answer from Why 3] occur?
→ [Answer]
**Why 5**: Why did [answer from Why 4] occur?
→ [Root cause]
**Fix**: [Addresses root cause]
**Prevention**: [Process/check to prevent recurrence]
模板 3:时间线重建
## Incident Timeline: [Event]
**Goal**: Reconstruct exact sequence leading to failure
| Time | Event | System State | Evidence |
|------|-------|--------------|----------|
| T-5min | [Normal operation] | [State] | [Logs] |
| T-2min | [Trigger event] | [State change] | [Logs/metrics] |
| T-30s | [Cascade starts] | [Degraded] | [Alerts] |
| T-0 | [Failure] | [Failed state] | [Error logs] |
| T+5min | [Recovery action] | [Recovering] | [Actions taken] |
**Critical Path**: [Sequence of events that led to failure]
**Alternative Scenarios**: [What could have prevented it at each step]
Python 调试模式
假设驱动的 Python 调试示例
```python """ Bug:API 端点间歇性返回 500 错误 症状:每 10 个请求中有 1 个失败,且总是涉及相同的用户 ID 假设:用户数据缓存中存在竞争条件 """
H1:用户之间的缓存键冲突
测试:在缓存操作周围添加详细日志
import logging logging.basicConfig(level=logging.DEBUG)
def get_user(user_id): cache_key = f"user:{user_id}" logging.debug(f"Fetching cache key: {cache_key} for user {user_id}")
cached = cache.get(cache_key)
if cached:
logging.debug(f"Cache hit: {cache_key} -> {cached}")
return cached
user = db.query(User).filter_by(id=user_id).first()
logging.debug(f"DB fetch for user {user_id}: {user}")
cache.set(cache_key, user, timeout=300)
logging.debug(f"Cache set: {cache_key} -> {user}")
return user
结果:发现 cache_key 在不同代码路径中的格式不同
根本原因:字符串格式不一致(f"user:{id}" 与 f"user_{id}")
```
使用上下文管理器进行高级调试
```python import time from contextlib import contextmanager
@contextmanager def debug_timer(operation_name): """为操作计时,并在耗时较长时记录日志""" start = time.perf_counter() try: yield finally: duration = time.perf_counter() - start if duration > 1.0: # 慢操作阈值 logging.warning( f"{operation_name} took {duration:.2f}s", extra={'operation': operation_name, 'duration': duration} )
用法
with debug_timer("database_query"): results = db.query(User).filter(...).all()
@contextmanager def hypothesis_test(hypothesis_name, expected_outcome): """测试并验证调试假设""" print(f"\n=== Testing: {hypothesis_name} ===") print(f"Expected: {expected_outcome}") start_state = capture_state() try: yield finally: end_state = capture_state() outcome = compare_states(start_state, end_state) print(f"Actual: {outcome}") print(f"Hypothesis {'CONFIRMED' if outcome == expected_outcome else 'REJECTED'}")
用法
with hypothesis_test( "H1: Database connection pool exhaustion", expected_outcome="pool_size increases during load" ): # 运行负载测试 for i in range(100): api_call() ```
使用高级技巧的 pdb 调试器
```python
基本断点
import pdb; pdb.set_trace()
Python 3.7+
breakpoint()
条件断点
if user_id == 12345: breakpoint()
事后调试(崩溃后调试)
import pdb try: risky_function() except Exception: pdb.post_mortem()
常用 pdb 命令
n(ext) - 执行下一行
s(tep) - 步入函数
c(ontinue) - 继续执行
p expr - 打印表达式
pp expr - 美化打印
l(ist) - 显示源代码
w(here) - 显示堆栈跟踪
u(p) - 上移一层堆栈帧
d(own) - 下移一层堆栈帧
b(reak) - 设置断点
cl(ear) - 清除断点
q(uit) - 退出调试器
高级:以编程方式调试
import pdb pdb.run('my_function()', globals(), locals()) ```
日志记录
```python import logging
logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('debug.log'), logging.StreamHandler() ] )
logger = logging.getLogger(name)
logger.debug("调试消息") logger.info("信息消息") logger.warning("警告消息") logger.error("错误消息", exc_info=True) ```
异常处理
```python import traceback
try: result = risky_operation() except Exception as e: # 记录完整的回溯信息 logger.error(f"操作失败:{e}") logger.error(traceback.format_exc())
# 或将回溯信息作为字符串获取
tb = traceback.format_exception(type(e), e, e.__traceback__)
error_details = ''.join(tb)
```
JavaScript/Node.js 调试
假设驱动的 JavaScript 调试示例
```javascript /**
- Bug:WebSocket 连接中的内存泄漏
- 症状:内存随时间增长,最终导致崩溃
- 假设:断开连接时未清理事件监听器 */
// H1:事件监听器不断累积 // 测试:跟踪监听器数量 class WebSocketManager { constructor() { this.connections = new Map(); this.debugListenerCounts = true; }
addConnection(userId, socket) { console.debug(`[H1 Test] 正在为用户 ${userId} 添加连接`);
if (this.debugListenerCounts) {
console.debug(\`[H1] 添加前的监听器数量:\${socket.listenerCount('message')}\`);
}
socket.on('message', (data) => this.handleMessage(userId, data));
socket.on('close', () => this.removeConnection(userId));
if (this.debugListenerCounts) {
console.debug(\`[H1] 添加后的监听器数量:\${socket.listenerCount('message')}\`);
}
this.connections.set(userId, socket);
}
removeConnection(userId) { console.debug(`[H1 Test] 正在移除用户 ${userId} 的连接`);
const socket = this.connections.get(userId);
if (socket) {
const messageListenerCount = socket.listenerCount('message');
console.debug(\`[H1] 仍附加的监听器:\${messageListenerCount}\`);
// 结果:发现同一事件上有 3 个以上监听器!
// 根本原因:重新连接时未移除监听器
socket.removeAllListeners();
this.connections.delete(userId);
}
} } ```
控制台高级调试
// Basic logging
console.log('Basic log');
console.error('Error message');
console.warn('Warning');
// Object inspection with depth
console.dir(object, { depth: null, colors: true });
console.table(array);
// Performance timing
console.time('operation');
// ... code ...
console.timeEnd('operation');
// Memory usage
console.memory; // Chrome only
// Stack trace
console.trace('Trace point');
// Grouping for organized logs
console.group('User Authentication Flow');
console.log('Step 1: Validate credentials');
console.log('Step 2: Generate token');
console.groupEnd();
// Conditional logging
const debug = (label, data) => {
if (process.env.DEBUG) {
console.log(`[DEBUG] ${label}:`, JSON.stringify(data, null, 2));
}
};
// Hypothesis testing helper
function testHypothesis(name, test, expected) {
console.group(`Testing: ${name}`);
console.log(`Expected: ${expected}`);
const actual = test();
console.log(`Actual: ${actual}`);
console.log(`Result: ${actual === expected ? 'PASS' : 'FAIL'}`);
console.groupEnd();
return actual === expected;
}
// Usage
testHypothesis(
'H1: Cache returns stale data',
() => cache.get('key').timestamp,
Date.now()
);
调试异步/Promise 问题
// Track promise chains
const debugPromise = (label, promise) => {
console.log(`[${label}] Started`);
return promise
.then(result => {
console.log(`[${label}] Resolved:`, result);
return result;
})
.catch(error => {
console.error(`[${label}] Rejected:`, error);
throw error;
});
};
// Usage
await debugPromise('DB Query', db.users.findOne({ id: 123 }));
// Debugging race conditions
async function debugRaceCondition() {
const operations = [
{ name: 'Op1', fn: async () => { await delay(100); return 'A'; } },
{ name: 'Op2', fn: async () => { await delay(50); return 'B'; } },
{ name: 'Op3', fn: async () => { await delay(150); return 'C'; } }
];
const results = await Promise.allSettled(
operations.map(async op => {
const start = Date.now();
const result = await op.fn();
const duration = Date.now() - start;
console.log(`${op.name} completed in ${duration}ms: ${result}`);
return { op: op.name, result, duration };
})
);
console.table(results.map(r => r.value));
}
// Debugging memory leaks with weak references
class DebugMemoryLeaks {
constructor() {
this.weakMap = new WeakMap();
this.strongRefs = new Map();
}
trackObject(id, obj) {
// Weak reference - will be GC'd if no other references
this.weakMap.set(obj, { id, created: Date.now() });
// Strong reference - prevents GC (potential leak source)
this.strongRefs.set(id, obj);
console.log(`Tracking ${id}: Strong refs=${this.strongRefs.size}`);
}
release(id) {
this.strongRefs.delete(id);
console.log(`Released ${id}: Strong refs=${this.strongRefs.size}`);
}
checkLeaks() {
console.log(`Potential leaks: ${this.strongRefs.size} strong references`);
return Array.from(this.strongRefs.keys());
}
}
Node.js 检查器
# Start with inspector
node --inspect app.js
node --inspect-brk app.js # Break on first line
# Debug with Chrome DevTools
# Open chrome://inspect
VS Code 调试配置
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Agent",
"program": "${workspaceFolder}/src/index.js",
"env": {
"NODE_ENV": "development"
}
}
]
}
容器调试
Docker
# View logs
docker logs <container> --tail=100 -f
# Execute shell
docker exec -it <container> /bin/sh
# Inspect container
docker inspect <container>
# Resource usage
docker stats <container>
调试正在运行的容器
docker run -it --rm \
--network=container:<target> \
nicolaka/netshoot
Kubernetes
# Pod 日志
kubectl logs <pod> -n agents -f
kubectl logs <pod> -n agents --previous # 上一次崩溃
# 在 Pod 中执行命令
kubectl exec -it <pod> -n agents -- /bin/sh
# 使用临时容器进行调试
kubectl debug <pod> -n agents -it --image=busybox
# 端口转发,以便在本地进行调试
kubectl port-forward <pod> 8080:8080 -n agents
# 事件
kubectl get events -n agents --sort-by='.lastTimestamp'
# 资源使用情况
kubectl top pods -n agents
日志分析
模式匹配
# 搜索日志中的错误
grep -i "error\|exception\|failed" app.log
# 统计出现次数
grep -c "ERROR" app.log
# 显示匹配项前后的内容
grep -B 5 -A 5 "OutOfMemory" app.log
# 按时间范围筛选
awk '/2024-01-15 10:00/,/2024-01-15 11:00/' app.log
JSON 日志
# 使用 jq 解析 JSON 日志
cat app.log | jq 'select(.level == "error")'
cat app.log | jq 'select(.timestamp > "2024-01-15T10:00:00")'
# 提取特定字段
cat app.log | jq -r '[.timestamp, .level, .message] | @tsv'
性能调试
Python 性能分析
# cProfile
import cProfile
cProfile.run('main()', 'output.prof')
# 行级性能分析器
@profile
def slow_function():
pass
# 内存分析器
from memory_profiler import profile
@profile
def memory_heavy():
pass
网络调试
# 检查连通性
ping <host>
telnet <host> <port>
nc -zv <host> <port>
# DNS 解析
nslookup <host>
dig <host>
# HTTP 调试
curl -v http://localhost:8080/health
curl -X POST -d '{"test": true}' -H "Content-Type: application/json" http://localhost:8080/api
常见调试检查清单
- 检查日志:应用、系统和容器日志
- 验证配置:环境变量、配置文件
- 测试连通性:网络、数据库、外部服务
- 检查资源:CPU、内存、磁盘空间
- 查看近期更改:Git 日志、部署历史
- 在本地复现:相同的环境、相同的数据
- 二分排查:缩小问题范围
调试决策树
使用此决策树确定合适的调试方法:
START: What kind of bug?
│
├─ Known error message/stack trace
│ └─ Use: Direct log analysis + Stack trace walkthrough
│
├─ Intermittent/Race condition
│ └─ Use: Extended thinking + Timeline reconstruction + Hypothesis-driven
│
├─ Performance degradation
│ └─ Use: Profiling + Hypothesis-driven + MECE analysis
│
├─ Distributed system failure
│ └─ Use: Extended thinking + Timeline reconstruction + Multi-system tracing
│
├─ Complex state bug
│ └─ Use: Extended thinking + Hypothesis-driven + pdb/debugger
│
├─ Memory leak
│ └─ Use: Memory profiling + Hypothesis-driven + Weak reference analysis
│
└─ Unknown root cause
└─ Use: Extended thinking + MECE analysis + 5 Whys
复杂调试的最佳实践
1. 记录调查过程
始终维护调试日志:
## Bug Investigation: [Title]
**Start Time**: 2024-01-15 10:00
**Investigator**: [Name]
### Timeline
- 10:00 - Started investigation, checked logs
- 10:15 - Found error pattern in auth service
- 10:30 - Hypothesis: Cache expiration race condition
- 10:45 - Added debug logging, confirmed hypothesis
- 11:00 - Implemented fix, testing
### Hypotheses Tested
- [x] H1: Cache race condition (CONFIRMED)
- [ ] H2: Database connection pool (REJECTED)
- [ ] H3: Network timeout (NOT TESTED)
### Root Cause
[Final determination]
### Fix Applied
[Solution details]
### Prevention
[How to prevent recurrence]
2. 运用科学方法
- 观察:收集症状、错误消息和日志
- 提出假设:生成 3-5 个合理的解释
- 预测:如果假设成立,会看到什么?
- 测试:设计实验以验证或证伪假设
- 分析:比较预测结果与实际结果
- 得出结论:用证据确认根本原因
3. 利用扩展思考
适合启用扩展思考的情况:
- 复杂度高:涉及 3 个以上相互影响的系统
- 不确定性高:存在多个同样合理的原因
- 影响重大:生产环境故障、安全问题、数据丢失
- 模式不明:没有明显的错误消息或日志
- 时间紧迫:需要在压力下采取系统化方法
4. 避免常见陷阱
AVOID:
- ❌ Changing multiple things at once (can't isolate cause)
- ❌ Assuming first hypothesis is correct (confirmation bias)
- ❌ Debugging without logs/evidence (guessing)
- ❌ Not documenting what you tried (repeating failed attempts)
- ❌ Skipping reproduction step (fix might not work)
DO:
- ✅ Change one variable at a time
- ✅ Test multiple hypotheses systematically
- ✅ Add instrumentation before debugging
- ✅ Keep investigation log
- ✅ Write regression test after fix
5. 调试插桩模式
# Python: Comprehensive debugging decorator
import functools
import time
import logging
def debug_trace(func):
"""Decorator to trace function execution with timing and state"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
func_name = func.__qualname__
logger.debug(f"→ Entering {func_name}")
logger.debug(f" Args: {args}")
logger.debug(f" Kwargs: {kwargs}")
start = time.perf_counter()
try:
result = func(*args, **kwargs)
duration = time.perf_counter() - start
logger.debug(f"← Exiting {func_name} ({duration:.3f}s)")
logger.debug(f" Result: {result}")
return result
except Exception as e:
duration = time.perf_counter() - start
logger.error(f"✗ Exception in {func_name} ({duration:.3f}s): {e}")
raise
return wrapper
# Usage
@debug_trace
def complex_operation(user_id, data):
# Your code here
pass
// JavaScript: Comprehensive debugging wrapper
function debugTrace(label) {
return function(target, propertyKey, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function(...args) {
console.log(\`→ Entering \${label || propertyKey}\`);
console.log(\` Args:\`, args);
const start = performance.now();
try {
const result = await originalMethod.apply(this, args);
const duration = performance.now() - start;
console.log(\`← Exiting \${label || propertyKey} (\${duration.toFixed(2)}ms)\`);
console.log(\` Result:\`, result);
return result;
} catch (error) {
const duration = performance.now() - start;
console.error(\`✗ Exception in \${label || propertyKey} (\${duration.toFixed(2)}ms):\`, error);
throw error;
}
};
return descriptor;
};
}
// Usage
class UserService {
@debugTrace('UserService.getUser')
async getUser(userId) {
// Your code here
}
}
交叉引用和相关技能
相关技能
此调试技能集成了:
-
extended-thinking(
.claude/skills/extended-thinking/SKILL.md)- 用途:根本原因未知的复杂错误
- 启用方式:在调试提示词中添加“use extended thinking”
- 优势:更深入的模式识别,系统化生成假设
-
complex-reasoning(
.claude/skills/complex-reasoning/SKILL.md)- 用途:需要逻辑推理链的多步骤调试
- 模式:用于错误调查的思维链、思维树
- 优势:针对复杂错误场景进行结构化推理
-
deep-analysis(
.claude/skills/deep-analysis/SKILL.md)- 用途:事后分析、根本原因调查
- 模式:全面的代码审查、架构分析
- 优势:识别表面错误之外的系统性问题
-
testing(
.claude/skills/testing/SKILL.md)- 用途:修复错误后编写回归测试
- 集成流程:错误 → 调试 → 修复 → 测试 → 验证
- 优势:确保错误不会再次发生
-
kubernetes(
.claude/skills/kubernetes/SKILL.md)- 用途:在 K8s 中调试分布式系统
- 工具:kubectl logs、exec、debug、events
- 集成:容器调试模式
何时组合使用技能
| 场景 | 组合使用的技能 | 原因 |
|---|---|---|
| 生产环境中断 | debugging + extended-thinking + kubernetes | 复杂的分布式系统需要深入推理 |
| 间歇性测试失败 | debugging + testing + complex-reasoning | 需要系统化地测试假设 |
| 性能回退 | debugging + deep-analysis | 根本原因可能与架构有关 |
| 安全漏洞 | debugging + extended-thinking + deep-analysis | 需要谨慎、全面的分析 |
| 内存泄漏 | debugging + complex-reasoning | 需要进行多步骤调查 |
集成示例
示例 1:复杂的生产环境错误
# Prompt combining skills
Claude, I have a complex production bug affecting multiple services.
Please use extended thinking and the debugging skill to help investigate.
Symptoms:
- API requests timeout intermittently (1 in 50 requests)
- Only affects authenticated users
- Started after recent deployment
- No obvious errors in logs
Please use:
1. MECE analysis to categorize possible causes
2. Hypothesis-driven debugging framework
3. Timeline reconstruction of recent changes
示例 2:内存泄漏调查
# Prompt combining skills
Claude, use complex reasoning and debugging skills to investigate a memory leak.
Context:
- Node.js service memory grows from 200MB to 2GB over 6 hours
- No errors logged
- Happens only in production, not staging
Apply:
1. Hypothesis-driven framework (generate 5 hypotheses)
2. Memory leak detection patterns (weak references)
3. Extended thinking for pattern recognition across codebase
快速参考卡
调试工作流摘要
1. OBSERVE
- Collect error messages, logs, metrics
- Identify patterns (frequency, conditions, scope)
- Document symptoms
2. HYPOTHESIZE (use extended thinking if complex)
- Generate 3-5 plausible hypotheses
- Rank by likelihood
- Design tests for each
3. TEST
- Change one variable at a time
- Add instrumentation (logging, tracing)
- Collect evidence
4. ANALYZE
- Compare predictions vs results
- Eliminate invalidated hypotheses
- Refine remaining hypotheses
5. FIX
- Implement solution
- Add regression test
- Document root cause
6. VALIDATE
- Verify fix in affected environment
- Monitor metrics
- Update documentation
工具选择指南
| 问题类型 | 主要工具 | 辅助工具 |
|---|---|---|
| 逻辑错误 | pdb/debugger | 日志、单元测试 |
| 性能问题 | Profiler | 假设测试、指标 |
| 内存泄漏 | Memory profiler | 弱引用、堆转储 |
| 异步/时序问题 | 时间线重建 | Extended thinking、日志 |
| 分布式问题 | 追踪(日志) | Kubernetes 工具、MECE 分析 |
| 原因未知 | Extended thinking | MECE、5 Whys、假设驱动分析 |
技能版本:2.0(增强版,集成了 extended thinking) 最后更新:2024-01-15 维护者:Golden Armada AI Agent Fleet