
---
#领域/Linux

#复盘/2

## 一句话描述

[____脚本错误处理____]

---

## 核心规范

>空想不如行动，积累胜于苛求。
>实践 > 沉淀 > 完美主义

实践不是盲目行动，而是带着“小目标、可验证“的方向试错，实践后必须沉淀（比如记录问题、总结规律），否则就是低水平重复。

实践大于沉淀，沉淀大于完美；完美是沉淀的终局方向，沉淀是实践的复盘产物；分域施策，避坑落地，始于行动，终于迭代。

---

## 三省沉淀法

- 达成了[___脚本处理异常错误_____]目标
- 遇到了[__目前脚本均为应用该处理______]问题
- 下次改进[_逐步引进错误处理机制_______]

## 个人理解

[__if、tray的判断、捕获，只是bash语法用法不同，道理是相通的______]

## 实践计划

#状态/待实践

1. [__编写错误处理模板______]
2. [__在脚本中引入错误处理模板______]
3. [________]

---

## 核心定义

trap 用于捕获[___系统信号_/ 脚本状态____]，暂停当前程序，并触发命令，再继续执行程序
可做异常处理、资源清理、流程控制

### 基础语法

```bash
# 绑定信号 + 执行命令
trap "要执行的命令" 信号名/信号编号 信号名/信号编号 # 可绑定多个

# 忽略指定信号
trap "" 信号名/信号编号 EXIT # EXIT 必用信号

# 重置信号为默认行为
trap - 信号名/信号编号
```

### 常用信号

| 信号名     | 信号编号 | 触发场景                | 核心用途         |
| ------- | ---- | ------------------- | ------------ |
| SIGINT  | 2    | 按 Ctrl+C 中断进程       | 捕获用户手动中断，做清理 |
| SIGTERM | 15   | kill 命令默认发送的终止信号    | 优雅终止脚本，释放资源  |
| EXIT    | 无编号  | 脚本正常 / 异常退出时触发      | 脚本收尾，清理临时文件  |
| SIGHUP  | 1    | 终端关闭 / 连接断开         | 处理后台脚本的终端断开  |
| SIGQUIT | 3    | 按 Ctrl+\ 退出并生成 core | 捕获强制退出，做日志记录 |


### 示例

#### ✅ 示例：脚本退出时自动清理

脚本运行生成临时文件，无论正常 / 异常退出，都要删除，避免垃圾文件残留

```bash
#!/bin/bash
# 定义临时文件路径
TMP_FILE="/tmp/test_trap.tmp"

# 绑定EXIT信号，退出时删除临时文件
trap "rm -f $TMP_FILE; echo '临时文件已清理，脚本退出'" EXIT

# 脚本主逻辑：创建临时文件并写入内容
echo "脚本运行中，生成临时文件" > $TMP_FILE
cat $TMP_FILE

# 模拟脚本正常结束
echo "脚本主逻辑执行完毕"
```

#### ✅ 示例：捕获用户中断（Ctrl+C），做优雅处理

用户手动中断脚本时，不直接退出，先提示并完成收尾。

```bash
#!/bin/bash
# 绑定SIGINT信号（Ctrl+C），捕获后执行自定义逻辑
trap "echo -e '\n用户手动中断，正在保存数据...'; exit 1" SIGINT

# 脚本主逻辑：模拟耗时任务
echo "脚本正在执行耗时任务，按Ctrl+C可中断"
for i in {1..5}; do
    echo "任务进度：$i/5"
    sleep 1
done

echo "任务执行完成"
```

#### ✅ 示例：忽略指定信号（防止脚本被误杀）

后台运行的脚本，忽略 Ctrl+C 中断，避免用户误操作终止。

```bash
#!/bin/bash
# 忽略SIGINT信号（Ctrl+C）
trap "" SIGINT

echo "脚本已忽略Ctrl+C，按Ctrl+\\可强制退出"
# 模拟后台循环任务
while true; do
    echo "脚本运行中..."
    sleep 2
done
```

#### ✅ 示例：多信号绑定同一处理逻辑

SIGINT、SIGTERM 触发时，执行相同的清理 + 退出逻辑。

```bash
#!/bin/bash
TMP_DIR="/tmp/trap_test"
mkdir -p $TMP_DIR

# 绑定多个信号，执行统一清理
trap "rm -rf $TMP_DIR; echo '清理临时目录，脚本退出'; exit" SIGINT SIGTERM EXIT

echo "脚本运行，临时目录：$TMP_DIR"
sleep 10
```



#### ✅ 示例：`$?`捕获最近命令错误码（局部捕获)

这里是关闭 set -euo pipefail，使用手动处理异常

```bash
#!/bin/bash
# set -euo pipefail

ls /不存在的目录
err_code=$?  # 捕获错误码
if [ $err_code -ne 0 ]; then
    echo "命令执行失败，错误码：$err_code"
    exit $err_code  # 主动退出并返回错误码
fi
```

#### ✅ 示例：trap 捕获全局错误

详见：[[20260204-备忘-linux-trap]]

```bash
#!/bin/bash
set -euo pipefail

# 错误处理函数：定位出错行+记录信息
error_handler() {
        local line=$1
        local err_code=$?
        echo "$(date +'%Y-%m-%d %H:%M:%S') - 第$line行失败，错误码：$err_code" >> /var/log/script_err.log
        exit $err_code
    }

# 捕获ERR（命令失败）、EXIT（脚本退出）信号
trap 'error_handler $LINENO' ERR EXIT

ls /不存在的目录  # 触发ERR信号，执行error_handler
```

```bash
#!/bin/bash
set -euo pipefail

# 清理函数：删除临时文件、释放资源
cleanup() {
    echo "执行清理操作..."
    rm -rf /临时目录  # 删除临时目录
    # 可选：关闭数据库连接、释放锁等
}

# 脚本退出时（无论成功/失败）执行清理
trap cleanup EXIT

# 模拟关键操作失败
mkdir /临时目录
ls /不存在的目录  # 触发错误，退出前执行cleanup
```


#### ✅ 示例：非关键命令允许失败

详见：[[Linux-set处理未定义和错误]]

```bash
#!/bin/bash
set -euo pipefail

# 临时关闭-e，允许rm失败（比如文件不存在）
set +e
rm /临时文件.txt  # 失败也不退出
set -e  # 恢复严格模式

# 关键命令：失败则退出
cp /源文件 /目标文件
```

#### ✅ 示例：临时错误重试

```bash
#!/bin/bash
set -euo pipefail

# 重试函数：参数1=重试次数，参数2=待执行命令
retry() {
    local retries=$1
    local cmd=$2
    local count=0
    
    while [ $count -lt $retries ]; do
        $cmd && return 0  # 执行成功则返回
        count=$((count+1))
        echo "重试第$count次..."
        sleep 1  # 重试间隔
    done
    echo "重试$retries次后仍失败"
    return 1
}

# 重试下载文件（网络可能临时失败）
retry 3 "curl -O https://example.com/test.txt"
```


### 避坑点

⚠️ 避坑点1：
    解决方案：

⚠️ 避坑点1：
    核心问题：
    解决方案：✅ 