backup materials and knowledge-base docs
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
# 常见错误模式
|
||||
|
||||
## 通用编程错误模式
|
||||
|
||||
### 1. Off-by-one Error(差一错误)
|
||||
|
||||
**描述**:循环或索引中出现 ±1 的偏差
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 错误:范围应该是 range(n) 而不是 range(n+1)
|
||||
for i in range(len(items) + 1):
|
||||
print(items[i]) # IndexError
|
||||
|
||||
# ✅ 正确
|
||||
for i in range(len(items)):
|
||||
print(items[i])
|
||||
```
|
||||
|
||||
### 2. Null/None 引用错误
|
||||
|
||||
**描述**:尝试访问 None 对象的属性或方法
|
||||
|
||||
**Python**:
|
||||
```python
|
||||
# ❌ 可能返回 None
|
||||
result = get_data()
|
||||
print(result.value) # AttributeError
|
||||
|
||||
# ✅ 检查 None
|
||||
result = get_data()
|
||||
if result is not None:
|
||||
print(result.value)
|
||||
```
|
||||
|
||||
**JavaScript**:
|
||||
```javascript
|
||||
// ❌ 可能是 null
|
||||
const user = getUser();
|
||||
console.log(user.name); // TypeError
|
||||
|
||||
// ✅ 使用可选链
|
||||
console.log(user?.name);
|
||||
```
|
||||
|
||||
### 3. 资源泄漏
|
||||
|
||||
**描述**:打开的资源(文件、连接)未正确关闭
|
||||
|
||||
**Python**:
|
||||
```python
|
||||
# ❌ 文件可能未关闭
|
||||
f = open("file.txt")
|
||||
content = f.read()
|
||||
# 如果发生异常,文件不会关闭
|
||||
|
||||
# ✅ 使用 with 语句
|
||||
with open("file.txt") as f:
|
||||
content = f.read()
|
||||
# 文件自动关闭
|
||||
```
|
||||
|
||||
### 4. 竞态条件
|
||||
|
||||
**描述**:多线程/进程间的时序依赖问题
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 检查后使用(TOCTOU)
|
||||
if os.path.exists("file.txt"):
|
||||
# 其他进程可能在这之间删除文件
|
||||
with open("file.txt") as f:
|
||||
content = f.read()
|
||||
|
||||
# ✅ 直接尝试并处理异常
|
||||
try:
|
||||
with open("file.txt") as f:
|
||||
content = f.read()
|
||||
except FileNotFoundError:
|
||||
content = None
|
||||
```
|
||||
|
||||
### 5. 忘记返回值
|
||||
|
||||
**描述**:函数没有显式返回值,导致返回 None
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 忘记返回结果
|
||||
def calculate(x, y):
|
||||
result = x + y
|
||||
# 忘记 return
|
||||
|
||||
# ✅ 正确返回
|
||||
def calculate(x, y):
|
||||
return x + y
|
||||
```
|
||||
|
||||
### 6. 错误的比较运算符
|
||||
|
||||
**描述**:使用 = 代替 ==,或混淆 is 和 ==
|
||||
|
||||
**Python**:
|
||||
```python
|
||||
# ❌ 赋值而不是比较
|
||||
if x = 5: # SyntaxError
|
||||
|
||||
# ❌ 使用 is 比较值
|
||||
if x is 5: # 不保证正确
|
||||
|
||||
# ✅ 正确
|
||||
if x == 5:
|
||||
```
|
||||
|
||||
### 7. 浮点数精度问题
|
||||
|
||||
**描述**:浮点数比较因精度问题失败
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 直接比较浮点数
|
||||
if 0.1 + 0.2 == 0.3: # False
|
||||
print("相等")
|
||||
|
||||
# ✅ 使用容差比较
|
||||
if abs((0.1 + 0.2) - 0.3) < 1e-9:
|
||||
print("相等")
|
||||
|
||||
# 或使用 math.isclose()
|
||||
import math
|
||||
if math.isclose(0.1 + 0.2, 0.3):
|
||||
print("相等")
|
||||
```
|
||||
|
||||
### 8. 字符串拼接性能问题
|
||||
|
||||
**描述**:在循环中使用 + 拼接字符串
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 低效:每次创建新字符串
|
||||
result = ""
|
||||
for item in items:
|
||||
result += str(item)
|
||||
|
||||
# ✅ 高效:使用列表和 join
|
||||
result = "".join(str(item) for item in items)
|
||||
```
|
||||
|
||||
## Python 特有模式
|
||||
|
||||
### 1. 可变默认参数
|
||||
|
||||
```python
|
||||
# ❌ 所有调用共享同一个列表
|
||||
def append(item, items=[]):
|
||||
items.append(item)
|
||||
return items
|
||||
|
||||
# ✅ 使用 None 作为默认值
|
||||
def append(item, items=None):
|
||||
if items is None:
|
||||
items = []
|
||||
items.append(item)
|
||||
return items
|
||||
```
|
||||
|
||||
### 2. 闭包变量绑定问题
|
||||
|
||||
```python
|
||||
# ❌ 所有函数使用相同的 i 值
|
||||
funcs = [lambda: i for i in range(3)]
|
||||
# 所有函数都返回 2
|
||||
|
||||
# ✅ 使用默认参数捕获值
|
||||
funcs = [lambda i=i: i for i in range(3)]
|
||||
```
|
||||
|
||||
### 3. 修改正在迭代的序列
|
||||
|
||||
```python
|
||||
# ❌ 迭代时修改列表
|
||||
items = [1, 2, 3, 4]
|
||||
for item in items:
|
||||
if item % 2 == 0:
|
||||
items.remove(item)
|
||||
|
||||
# ✅ 创建新列表或使用副本
|
||||
items = [item for item in items if item % 2 != 0]
|
||||
|
||||
# 或
|
||||
for item in items[:]:
|
||||
if item % 2 == 0:
|
||||
items.remove(item)
|
||||
```
|
||||
|
||||
## JavaScript/TypeScript 特有模式
|
||||
|
||||
### 1. this 绑定问题
|
||||
|
||||
```javascript
|
||||
// ❌ this 丢失上下文
|
||||
class Counter {
|
||||
count = 0;
|
||||
increment() {
|
||||
setTimeout(function() {
|
||||
this.count++; // this 不是 Counter 实例
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 使用箭头函数
|
||||
class Counter {
|
||||
count = 0;
|
||||
increment() {
|
||||
setTimeout(() => {
|
||||
this.count++; // this 正确绑定
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 异步错误处理
|
||||
|
||||
```javascript
|
||||
// ❌ 没有处理 Promise 错误
|
||||
async function getData() {
|
||||
const response = await fetch(url);
|
||||
return response.json(); // 如果失败会抛出异常
|
||||
}
|
||||
|
||||
// ✅ 使用 try-catch
|
||||
async function getData() {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error("获取数据失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 数组/对象引用
|
||||
|
||||
```javascript
|
||||
// ❌ 直接赋值会复制引用
|
||||
const arr1 = [1, 2, 3];
|
||||
const arr2 = arr1;
|
||||
arr2.push(4); // arr1 也会被修改
|
||||
|
||||
// ✅ 创建副本
|
||||
const arr2 = [...arr1]; // 或 arr1.slice()
|
||||
|
||||
// 对象
|
||||
const obj1 = { a: 1 };
|
||||
const obj2 = { ...obj1 }; // 或 Object.assign({}, obj1)
|
||||
```
|
||||
|
||||
## 并发错误模式
|
||||
|
||||
### 1. 死锁
|
||||
|
||||
```python
|
||||
# ❌ 可能死锁
|
||||
import threading
|
||||
|
||||
lock1 = threading.Lock()
|
||||
lock2 = threading.Lock()
|
||||
|
||||
def thread1():
|
||||
with lock1:
|
||||
with lock2:
|
||||
# 操作
|
||||
|
||||
def thread2():
|
||||
with lock2:
|
||||
with lock1: # 死锁
|
||||
# 操作
|
||||
```
|
||||
|
||||
### 2. 数据竞争
|
||||
|
||||
```python
|
||||
# ❌ 多个线程同时修改共享变量
|
||||
counter = 0
|
||||
|
||||
def increment():
|
||||
global counter
|
||||
counter += 1 # 非原子操作
|
||||
|
||||
# ✅ 使用锁
|
||||
counter = 0
|
||||
lock = threading.Lock()
|
||||
|
||||
def increment():
|
||||
global counter
|
||||
with lock:
|
||||
counter += 1
|
||||
```
|
||||
|
||||
## 预防措施
|
||||
|
||||
1. **使用类型检查**:TypeScript、Python 类型注解
|
||||
2. **编写单元测试**:覆盖边界条件
|
||||
3. **使用静态分析工具**:pylint、eslint
|
||||
4. **代码审查**:让他人检查代码
|
||||
5. **使用防御性编程**:验证输入、处理异常
|
||||
@@ -0,0 +1,29 @@
|
||||
# Debugging Tools
|
||||
|
||||
## Python
|
||||
```bash
|
||||
python -m pdb script.py
|
||||
python -m traceback your_script.py
|
||||
pytest -x -vv tests/test_target.py
|
||||
```
|
||||
|
||||
## Node.js
|
||||
```bash
|
||||
node --inspect-brk app.js
|
||||
node --trace-warnings app.js
|
||||
npm test -- --runInBand
|
||||
```
|
||||
|
||||
## Git
|
||||
```bash
|
||||
git bisect start
|
||||
git bisect bad
|
||||
git bisect good <known-good-commit>
|
||||
```
|
||||
|
||||
## Shell
|
||||
```bash
|
||||
bash -n script.sh
|
||||
bash -x script.sh
|
||||
shellcheck script.sh
|
||||
```
|
||||
@@ -0,0 +1,14 @@
|
||||
# JavaScript / TypeScript Error Guide
|
||||
|
||||
## Frequent failure classes
|
||||
- `TypeError` from undefined/null access
|
||||
- async error swallowing in `Promise` chains
|
||||
- `this` binding mismatches
|
||||
- stale closure bugs in hooks or event handlers
|
||||
- ESM / CJS import mismatches
|
||||
|
||||
## Minimum debugging flow
|
||||
1. copy the full stack trace,
|
||||
2. identify whether the failure is runtime, bundler, or type-level,
|
||||
3. confirm the failing object/value before changing logic,
|
||||
4. reproduce with the smallest possible input.
|
||||
@@ -0,0 +1,311 @@
|
||||
# Python 错误详解
|
||||
|
||||
## 常见内置异常类型
|
||||
|
||||
### 1. SyntaxError(语法错误)
|
||||
|
||||
**特征**:代码无法解析,在运行前就被检测到
|
||||
|
||||
**常见原因**:
|
||||
- 括号不匹配
|
||||
- 缺少冒号
|
||||
- 缩进不正确
|
||||
- 引号不匹配
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 缺少冒号
|
||||
if True
|
||||
print("missing colon")
|
||||
|
||||
# ✅ 正确
|
||||
if True:
|
||||
print("has colon")
|
||||
```
|
||||
|
||||
### 2. IndentationError(缩进错误)
|
||||
|
||||
**特征**:缩进不一致或使用错误的缩进
|
||||
|
||||
**常见原因**:
|
||||
- 混用 Tab 和空格
|
||||
- 缩进级别不正确
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 混用空格和 Tab
|
||||
def test():
|
||||
print("mixed") # Tab
|
||||
print("spaces") # 空格
|
||||
|
||||
# ✅ 统一使用 4 个空格
|
||||
def test():
|
||||
print("spaces")
|
||||
print("consistent")
|
||||
```
|
||||
|
||||
### 3. NameError(名称错误)
|
||||
|
||||
**特征**:变量或函数名不存在
|
||||
|
||||
**常见原因**:
|
||||
- 变量未定义就使用
|
||||
- 函数名拼写错误
|
||||
- 变量作用域问题
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 变量未定义
|
||||
print(undefined_var)
|
||||
|
||||
# ✅ 先定义再使用
|
||||
my_var = 42
|
||||
print(my_var)
|
||||
```
|
||||
|
||||
### 4. TypeError(类型错误)
|
||||
|
||||
**特征**:操作或函数应用于错误的数据类型
|
||||
|
||||
**常见原因**:
|
||||
- 拼接不同类型
|
||||
- 函数参数类型错误
|
||||
- 对不支持的操作使用运算符
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 拼接字符串和数字
|
||||
result = "Value: " + 42
|
||||
|
||||
# ✅ 转换类型
|
||||
result = "Value: " + str(42)
|
||||
# 或使用 f-string
|
||||
result = f"Value: {42}"
|
||||
```
|
||||
|
||||
### 5. AttributeError(属性错误)
|
||||
|
||||
**特征**:对象没有指定的属性或方法
|
||||
|
||||
**常见原因**:
|
||||
- 属性名拼写错误
|
||||
- 对象类型不是预期的
|
||||
- 大小写错误
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 列表没有 append 以外的方法
|
||||
my_list = [1, 2, 3]
|
||||
my_list.push(4) # 列表没有 push 方法
|
||||
|
||||
# ✅ 使用正确的方法
|
||||
my_list.append(4)
|
||||
```
|
||||
|
||||
### 6. KeyError(键错误)
|
||||
|
||||
**特征**:字典中不存在指定的键
|
||||
|
||||
**常见原因**:
|
||||
- 键名拼写错误
|
||||
- 键不存在于字典中
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
data = {"name": "Alice"}
|
||||
|
||||
# ❌ 直接访问不存在的键
|
||||
age = data["age"] # KeyError
|
||||
|
||||
# ✅ 使用 get() 方法
|
||||
age = data.get("age", 0) # 返回默认值 0
|
||||
```
|
||||
|
||||
### 7. IndexError(索引错误)
|
||||
|
||||
**特征**:序列索引超出范围
|
||||
|
||||
**常见原因**:
|
||||
- 索引为负数(除非是有意为之)
|
||||
- 索引大于序列长度-1
|
||||
- 序列为空时访问索引
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
items = [1, 2, 3]
|
||||
|
||||
# ❌ 索引超出范围
|
||||
item = items[5] # IndexError
|
||||
|
||||
# ✅ 检查长度后再访问
|
||||
if len(items) > 5:
|
||||
item = items[5]
|
||||
else:
|
||||
item = None
|
||||
```
|
||||
|
||||
### 8. ValueError(值错误)
|
||||
|
||||
**特征**:参数类型正确但值不合适
|
||||
|
||||
**常见原因**:
|
||||
- 字符串转整数失败
|
||||
- 数学运算值域错误
|
||||
- 参数值不在允许范围内
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 无法转换为整数
|
||||
num = int("abc")
|
||||
|
||||
# ✅ 处理可能的错误
|
||||
try:
|
||||
num = int(input())
|
||||
except ValueError:
|
||||
num = 0
|
||||
```
|
||||
|
||||
### 9. ImportError / ModuleNotFoundError(导入错误)
|
||||
|
||||
**特征**:无法导入模块
|
||||
|
||||
**常见原因**:
|
||||
- 模块未安装
|
||||
- 模块路径不在 PYTHONPATH 中
|
||||
- 模块名拼写错误
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 模块未安装
|
||||
import missing_module
|
||||
|
||||
# 解决方法:安装模块
|
||||
# pip install missing-module
|
||||
```
|
||||
|
||||
### 10. FileNotFoundError(文件未找到错误)
|
||||
|
||||
**特征**:尝试打开不存在的文件
|
||||
|
||||
**常见原因**:
|
||||
- 文件路径错误
|
||||
- 文件不存在
|
||||
- 相对路径使用错误
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# ❌ 文件不存在
|
||||
with open("missing.txt") as f:
|
||||
content = f.read()
|
||||
|
||||
# ✅ 使用 try-except 或检查文件存在
|
||||
try:
|
||||
with open("file.txt") as f:
|
||||
content = f.read()
|
||||
except FileNotFoundError:
|
||||
content = ""
|
||||
```
|
||||
|
||||
## 异常处理最佳实践
|
||||
|
||||
### 1. 捕获具体异常
|
||||
|
||||
```python
|
||||
# ❌ 捕获所有异常(不良实践)
|
||||
try:
|
||||
result = dangerous_operation()
|
||||
except:
|
||||
pass
|
||||
|
||||
# ✅ 捕获具体异常
|
||||
try:
|
||||
result = dangerous_operation()
|
||||
except (ValueError, TypeError) as e:
|
||||
logger.error(f"操作失败: {e}")
|
||||
```
|
||||
|
||||
### 2. 使用 finally 清理资源
|
||||
|
||||
```python
|
||||
try:
|
||||
file = open("data.txt", "r")
|
||||
content = file.read()
|
||||
except FileNotFoundError:
|
||||
content = ""
|
||||
finally:
|
||||
# 无论是否发生异常都会执行
|
||||
if 'file' in locals():
|
||||
file.close()
|
||||
```
|
||||
|
||||
### 3. 使用上下文管理器
|
||||
|
||||
```python
|
||||
# ✅ 推荐:使用 with 语句
|
||||
with open("data.txt", "r") as file:
|
||||
content = file.read()
|
||||
# 文件会自动关闭
|
||||
```
|
||||
|
||||
### 4. 链式异常
|
||||
|
||||
```python
|
||||
try:
|
||||
process_data(data)
|
||||
except ValueError as e:
|
||||
# 使用 raise from 保留原始异常
|
||||
raise RuntimeError("数据处理失败") from e
|
||||
```
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 1. 使用 traceback 模块
|
||||
|
||||
```python
|
||||
import traceback
|
||||
|
||||
try:
|
||||
risky_operation()
|
||||
except Exception:
|
||||
# 打印完整的堆栈跟踪
|
||||
traceback.print_exc()
|
||||
```
|
||||
|
||||
### 2. 使用 pdb 调试器
|
||||
|
||||
```python
|
||||
import pdb
|
||||
|
||||
# 在代码中设置断点
|
||||
pdb.set_trace()
|
||||
|
||||
# 或使用 breakpoint() (Python 3.7+)
|
||||
breakpoint()
|
||||
```
|
||||
|
||||
### 3. 使用 logging 模块
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.debug("调试信息")
|
||||
logger.info("普通信息")
|
||||
logger.warning("警告")
|
||||
logger.error("错误")
|
||||
logger.critical("严重错误")
|
||||
```
|
||||
|
||||
## 常见错误排查清单
|
||||
|
||||
- [ ] 检查拼写(变量名、函数名、属性名)
|
||||
- [ ] 检查数据类型(使用 type() 函数)
|
||||
- [ ] 检查变量值(使用 print() 或调试器)
|
||||
- [ ] 检查索引和键是否在范围内
|
||||
- [ ] 检查文件路径是否正确
|
||||
- [ ] 检查缩进是否一致
|
||||
- [ ] 检查括号、引号是否匹配
|
||||
- [ ] 检查是否正确导入了模块
|
||||
- [ ] 检查异常是否被正确处理
|
||||
@@ -0,0 +1,236 @@
|
||||
# Bash/Zsh 脚本错误详解
|
||||
|
||||
## 常见错误类型
|
||||
|
||||
### 1. Command Not Found
|
||||
|
||||
**特征**:bash: command: command not found
|
||||
|
||||
**常见原因**:
|
||||
- 命令拼写错误
|
||||
- 命令未安装
|
||||
- PATH 环境变量不正确
|
||||
- 脚本 shebang 错误
|
||||
|
||||
**示例**:
|
||||
```bash
|
||||
# 拼写错误
|
||||
pyhon script.py # command not found
|
||||
|
||||
# 正确拼写
|
||||
python script.py
|
||||
|
||||
# PATH 问题
|
||||
/usr/local/bin/mycommand # 如果 PATH 不包含 /usr/local/bin
|
||||
|
||||
# 使用完整路径或添加到 PATH
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
mycommand
|
||||
```
|
||||
|
||||
### 2. Syntax Error
|
||||
|
||||
**特征**:syntax error near unexpected token
|
||||
|
||||
**常见原因**:
|
||||
- 缺少 then/fi/done/ esac
|
||||
- 括号不匹配
|
||||
- 操作符缺少空格
|
||||
|
||||
**示例**:
|
||||
```bash
|
||||
# 缺少 then
|
||||
if [ 1 -eq 1 ]
|
||||
echo "yes" # syntax error
|
||||
|
||||
# 正确
|
||||
if [ 1 -eq 1 ]; then
|
||||
echo "yes"
|
||||
fi
|
||||
```
|
||||
|
||||
### 3. Permission Denied
|
||||
|
||||
**特征**:bash: ./script.sh: Permission denied
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 添加执行权限
|
||||
chmod +x script.sh
|
||||
|
||||
# 或使用 bash 运行
|
||||
bash script.sh
|
||||
```
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 1. 使用 set -x 追踪执行
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -x # 启用命令追踪
|
||||
|
||||
name="John"
|
||||
echo "Hello $name"
|
||||
|
||||
# 输出:
|
||||
# + name=John
|
||||
# + echo 'Hello John'
|
||||
# Hello John
|
||||
```
|
||||
|
||||
### 2. 使用 set -e 遇错退出
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e # 任何命令失败时退出
|
||||
|
||||
cd /nonexistent # 脚本在此处退出
|
||||
echo "This won't run"
|
||||
```
|
||||
|
||||
### 3. 使用 set -u 检测未定义变量
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -u # 未定义变量时报错
|
||||
|
||||
echo $undefined_var # 报错并退出
|
||||
```
|
||||
|
||||
### 4. 组合使用调试选项
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -xeuo pipefail # 严格模式
|
||||
|
||||
# -x: 打印每个命令
|
||||
# -e: 错误时退出
|
||||
# -u: 未定义变量报错
|
||||
# -o pipefail: 管道失败则失败
|
||||
```
|
||||
|
||||
### 5. 使用 trap 捕获错误
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 在脚本退出时执行清理
|
||||
trap 'echo "Script exited with code $?"' EXIT
|
||||
|
||||
# 在错误时执行
|
||||
trap 'echo "Error on line $LINENO"' ERR
|
||||
|
||||
# 在中断时执行
|
||||
trap 'echo "Interrupted"; cleanup' INT
|
||||
```
|
||||
|
||||
## 错误处理模式
|
||||
|
||||
### 1. 检查命令退出码
|
||||
|
||||
```bash
|
||||
# 检查上一个命令是否成功
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Success"
|
||||
else
|
||||
echo "Failed"
|
||||
fi
|
||||
|
||||
# 或使用 ||
|
||||
command || { echo "Failed"; exit 1; }
|
||||
|
||||
# 或使用 &&
|
||||
command && echo "Success" || echo "Failed"
|
||||
```
|
||||
|
||||
### 2. 使用函数封装错误处理
|
||||
|
||||
```bash
|
||||
# 定义错误处理函数
|
||||
die() {
|
||||
local message=$1
|
||||
echo "Error: $message" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 使用
|
||||
[ -f "$file" ] || die "File not found: $file"
|
||||
```
|
||||
|
||||
### 3. 验证输入参数
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 检查参数数量
|
||||
[ $# -ge 1 ] || die "Usage: $0 <arg1> [arg2]"
|
||||
|
||||
# 检查文件存在
|
||||
[ -f "$1" ] || die "File not found: $1"
|
||||
|
||||
# 检查目录存在
|
||||
[ -d "$2" ] || die "Directory not found: $2"
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 始终使用 shebang
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 或
|
||||
#!/usr/bin/env bash
|
||||
```
|
||||
|
||||
### 2. 使用 set -euo pipefail
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
```
|
||||
|
||||
### 3. 引用所有变量
|
||||
|
||||
```bash
|
||||
# 除非确定变量不包含空格或通配符
|
||||
echo "$var"
|
||||
```
|
||||
|
||||
### 4. 使用 [[ ]] 而不是 [ ]
|
||||
|
||||
```bash
|
||||
# [[ 更强大且更安全
|
||||
if [[ $name == "John" ]]; then
|
||||
if [[ -f $file && $size -gt 100 ]]; then
|
||||
```
|
||||
|
||||
### 5. 使用 $(command) 而不是反引号
|
||||
|
||||
```bash
|
||||
# $() 更易读且可嵌套
|
||||
result=$(command1 $(command2))
|
||||
```
|
||||
|
||||
### 6. 使用函数组织代码
|
||||
|
||||
```bash
|
||||
my_function() {
|
||||
local arg1=$1
|
||||
local arg2=$2
|
||||
# 函数体
|
||||
}
|
||||
|
||||
my_function "value1" "value2"
|
||||
```
|
||||
|
||||
## ShellCheck 静态分析
|
||||
|
||||
ShellCheck 是一个 Shell 脚本静态分析工具:
|
||||
|
||||
```bash
|
||||
# 安装 ShellCheck
|
||||
brew install shellcheck # macOS
|
||||
apt install shellcheck # Ubuntu
|
||||
|
||||
# 使用
|
||||
shellcheck script.sh
|
||||
```
|
||||
Reference in New Issue
Block a user