第 12 章 · Shell 脚本进阶
本章目标:用 here document 生成配置片段;用 trap 保证临时文件不泄漏;理解 cron 定时任务格式;用 数组 批量处理 slug;写 deploy-pre.sh 串联 ch11 check_log 与 ch14 部署前检查。
学时建议:4 小时(含 2 小时跟练)
前置:linux-shell ch11;check_log.sh 已存在。
12.1 场景说明:部署脚本半途失败,/tmp 堆满垃圾
ch11 的脚本用 mktemp 写临时文件。若脚本被 Ctrl+C 打断,或中间命令失败,tmp 文件可能留在磁盘上。生产部署脚本还会:
- 根据模板生成 nginx 片段(ch14)
- 每天 9:00 自动跑 check_log.sh(cron)
本章补:here doc、trap、cron、数组。
12.2 学完你能
| 能力 | 验收 |
|---|---|
| here doc | 输出多行 nginx 配置块 |
| trap EXIT | 脚本中断后 tmp 仍被删 |
| crontab | 读懂「分 时 日 月 周」五段 |
| 数组 | 遍历多个 slug |
| deploy-pre | 部署前跑 check_log,失败则 exit |
12.3 here document:脚本里塞多行文本
步骤 1 — 写 gen_nginx_snippet.sh
cat > ~/dev-workspace/shop-demo/scripts/gen_nginx_snippet.sh << 'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
read -r -d '' NGINX << 'EOF' || true
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
EOF
echo "$NGINX"
SCRIPT
chmod +x ~/dev-workspace/shop-demo/scripts/gen_nginx_snippet.sh
步骤 2 — 运行
~/dev-workspace/shop-demo/scripts/gen_nginx_snippet.sh
你应该看到 完整 location /api/ { ... } 块。
读懂引号:
| 写法 | 变量是否展开 |
|---|---|
<< 'EOF' | 不展开 $host(字面量给 nginx 用) |
<< EOF | 展开当前 Shell 变量 |
为什么 read -r -d '' ... || true:read -d '' 读 heredoc 到变量;某些 bash 版本 EOF 结束会返回非 0,加 || true 避免 set -e 误杀。
12.4 trap:退出时自动清理
步骤 1 — with_tmp.sh
cat > ~/dev-workspace/shop-demo/scripts/with_tmp.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
TMP=$(mktemp)
trap 'rm -f "$TMP"' EXIT
echo "temp file: $TMP"
echo "data line" > "$TMP"
cat "$TMP"
echo "done — on exit tmp removed"
EOF
chmod +x ~/dev-workspace/shop-demo/scripts/with_tmp.sh
步骤 2 — 正常跑
~/dev-workspace/shop-demo/scripts/with_tmp.sh
ls "$TMP" 2>/dev/null || echo "tmp already gone (expected)"
步骤 3 — 模拟失败仍清理
在脚本末尾 exit 1 前已有 trap;或运行:
bash -c 'TMP=$(mktemp); trap "rm -f \$TMP" EXIT; echo hi; exit 1'
ls "$TMP" 2>/dev/null || echo "cleaned after exit 1"
为什么 kill -9 不会跑 trap——正常 exit 和 Ctrl+C(INT)一般会。
12.5 cron:定时跑 check_log
步骤 1 — 看当前 crontab
crontab -l 2>/dev/null || echo "(尚无 crontab)"
步骤 2 — 理解五段
分 时 日 月 周 命令(必须绝对路径)
* * * * *
| 示例 | 含义 |
|---|---|
0 9 * | 每天 9:00 |
/5 * | 每 5 分钟 |
0 9 1-5 | 工作日 9:00 |
步骤 3 — 教学用条目(慎用生产)