name: 漏洞侦探 description: 此技能应在用户要求“调试这个”、“修复这个错误”、“调查这个漏洞”、“排除这个问题”、“找到问题”、“有些东西坏了”、“这个不工作”、“为什么失败”或报告错误/异常/漏洞时使用。提供系统调试工作流程和常见错误模式。 version: 0.1.0
漏洞侦探
一个系统调试工作流程,用于调查和解决代码错误、异常和失败。提供结构化调试方法和常见错误模式识别。
核心理念
调试是一个科学问题解决过程,需要:
- 理解问题 - 清晰定义症状和预期行为
- 收集证据 - 收集错误消息、日志、堆栈跟踪
- 形成假设 - 基于证据推断可能原因
- 验证假设 - 通过实验确认或排除原因
- 解决问题 - 应用修复并验证
调试工作流程
步骤1:理解问题
在开始调试前,澄清以下信息:
需要收集的信息:
- 完整错误消息内容
- 错误的确切位置(文件名和行号)
- 重现步骤(如何触发错误)
- 预期行为与实际行为
- 环境信息(操作系统、版本、依赖项)
问题模板:
1. 确切的错误消息是什么?
2. 错误发生在哪个文件和行?
3. 如何重现这个问题?提供详细步骤。
4. 预期结果是什么?实际发生了什么?
5. 最近哪些更改可能引入了这个问题?
步骤2:分析错误类型
基于错误类型选择调试策略:
| 错误类型 | 特征 | 调试方法 |
|---|---|---|
| 语法错误 | 代码无法解析 | 检查语法、括号匹配、引号 |
| 导入错误 | ModuleNotFoundError | 检查模块安装、路径配置 |
| 类型错误 | TypeError | 检查数据类型、类型转换 |
| 属性错误 | AttributeError | 检查对象属性是否存在 |
| 键错误 | KeyError | 检查字典键是否存在 |
| 索引错误 | IndexError | 检查列表/数组索引范围 |
| 空引用错误 | NoneType/NullPointerException | 检查变量是否为None |
| 网络错误 | ConnectionError/Timeout | 检查网络连接、URL、超时设置 |
| 权限错误 | PermissionError | 检查文件权限、用户权限 |
| 资源错误 | FileNotFoundError | 检查文件路径是否存在 |
步骤3:定位问题源
使用以下方法定位问题:
1. 二分查找法
- 注释掉一半代码,检查问题是否持续
- 逐步缩小范围,直到找到有问题的代码
2. 日志跟踪
- 在关键位置添加打印/日志语句
- 跟踪变量值变化
- 确认代码执行路径
3. 断点调试
- 使用调试器断点功能
- 逐步执行代码
- 检查变量状态
4. 堆栈跟踪分析
- 从错误消息中的堆栈跟踪找到调用链
- 确定错误的直接原因
- 追溯到根本原因
步骤4:形成和验证假设
假设框架:
假设:[问题描述] 导致 [错误现象]
验证步骤:
1. [验证方法1]
2. [验证方法2]
预期结果:
- 如果假设正确:[预期现象]
- 如果假设错误:[预期现象]
步骤5:应用修复
修复后验证:
- 原始错误已解决
- 没有引入新错误
- 相关功能仍正常工作
- 添加测试以防止回归
Python 常见错误模式
1. 缩进错误
2. 可变默认参数
3. 循环中的闭包问题
4. 迭代时修改列表
5. 使用 is 进行字符串比较
6. 忘记调用 super().__init__()
JavaScript/TypeScript 常见错误模式
1. this 绑定问题
2. 异步错误处理
3. 对象引用比较
Bash/Zsh 常见错误模式
1. 间距问题
# ❌ 赋值中不允许有空格
name = "John" # 错误:尝试运行 'name' 命令
# ✅ 正确赋值
name="John"
# ❌ 条件测试中缺少空格
if[$name -eq 1]; then # 错误
# ✅ 正确
if [ $name -eq 1 ]; then
2. 引用问题
# ❌ 变量在单引号内不扩展
echo 'The value is $var' # 输出: The value is $var
# ✅ 使用双引号
echo "The value is $var" # 输出: The value is actual_value
# ❌ 使用反引号进行命令替换(易混淆)
result=`command`
# ✅ 使用 $()
result=$(command)
3. 未引用的变量
# ❌ 未引用变量,空值导致错误
rm -rf $dir/* # 如果 dir 为空,删除当前目录所有文件
# ✅ 始终引用变量
[ -n "$dir" ] && rm -rf "$dir"/*
# 或使用 set -u 防止未定义变量
set -u # 或 set -o nounset
4. 循环中的变量作用域
# ❌ 管道创建子shell,外部变量不变
cat file.txt | while read line; do
count=$((count + 1)) # 外部 count 不会改变
done
echo "Total: $count" # 输出 0
# ✅ 使用进程替换或重定向
while read line; do
count=$((count + 1))
done < file.txt
echo "Total: $count" # 正确输出
5. 数组操作
# ❌ 不正确的数组访问
arr=(1 2 3)
echo $arr[1] # 输出 1[1]
# ✅ 正确的数组访问
echo ${arr[1]} # 输出 2
echo ${arr[@]} # 输出所有元素
echo ${#arr[@]} # 输出数组长度
6. 字符串比较
# ❌ 使用 = 进行字符串比较
if [ $name = "John" ]; then # 在某些shell中不标准
# ✅ 使用 = 或 ==
if [ "$name" = "John" ]; then
if [[ "$name" == "John" ]]; then
# ❌ 使用 -eq 进行数字比较而不是 =
if [ $age = 18 ]; then # 错误
# ✅ 使用算术运算符进行数字比较
if [ $age -eq 18 ]; then
if (( age == 18 )); then
7. 命令失败后继续执行
# ❌ 命令失败后继续执行
cd /nonexistent
rm file.txt # 删除当前目录中的 file.txt
# ✅ 使用 set -e 在错误时退出
set -e # 或 set -o errexit
cd /nonexistent # 脚本在此退出
rm file.txt
# 或检查命令是否成功
cd /nonexistent || exit 1
常见调试命令
Python pdb 调试器
Node.js 检查器
Git 二分查找
Bash 调试
# 在调试模式下运行脚本
bash -x script.sh # 打印每个命令
bash -v script.sh # 打印命令源
bash -n script.sh # 语法检查,不执行
# 在脚本内启用调试
set -x # 启用命令跟踪
set -v # 启用详细模式
set -e # 在错误时退出
set -u # 未定义变量时错误
set -o pipefail # 如果管道中任何命令失败则失败
预防性调试
1. 使用类型检查
2. 输入验证
3. 防御性编程
4. 日志记录
调试检查表
开始前
- [ ] 获取完整错误消息
- [ ] 记录错误的堆栈跟踪
- [ ] 确认重现步骤
- [ ] 理解预期行为
调试期间
- [ ] 检查最近代码更改
- [ ] 使用二分查找定位问题
- [ ] 添加日志跟踪变量
- [ ] 验证假设
解决后
- [ ] 确认原始错误已修复
- [ ] 测试相关功能
- [ ] 添加测试以防止回归
- [ ] 记录问题和解决方案
附加资源
参考文件
有关详细调试技术和模式:
references/python-errors.md- Python 错误详情references/javascript-errors.md- JavaScript/TypeScript 错误详情references/shell-errors.md- Bash/Zsh 脚本错误详情references/debugging-tools.md- 调试工具使用指南references/common-patterns.md- 常见错误模式
示例文件
工作调试示例:
examples/debugging-workflow.py- 完整调试工作流程示例examples/error-handling-patterns.py- 错误处理模式示例examples/debugging-workflow.sh- Shell 脚本调试示例