with one click
shell-scripting-safe
写 shell/bash 脚本时使用。防止静默失败与误删。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
写 shell/bash 脚本时使用。防止静默失败与误删。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
做 Cocos Creator 多机型/多分辨率适配时使用。Canvas、Widget、安全区。
Cocos Creator 用 AssetBundle 做分包/远程资源时使用。加载、释放、依赖、缓存。
优化 Cocos Creator 渲染性能时使用。合批、图集、动静分离、Label。
给 Cocos Creator 原生包做热更新时使用。version manifest、增量、校验、回滚。
写 Cocos Creator 动效/动画时使用。tween、Animation、Spine、性能与清理。
做 Cocos Creator 大量条目列表时使用。虚拟列表、节点复用。
| name | shell-scripting-safe |
| description | 写 shell/bash 脚本时使用。防止静默失败与误删。 |
| category | devops |
| tags | ["shell","bash","脚本"] |
.sh / bash 脚本。set -euo pipefail,让错误立即暴露规则: 每个脚本第一行(shebang 之后)加 set -euo pipefail,确保命令非零退出立即终止脚本(-e),引用未定义变量报错(-u),管道中间命令失败也能被捕获(-o pipefail)。
为什么: AI 生成的 bash 脚本默认不加这三个选项,导致静默失败危害极大。曾见真实事故:TARGET_DIR="" 变量赋值失败(来自上一条命令出错),下一步 rm -rf "$TARGET_DIR/" 展开为 rm -rf "/" 并成功执行——因为没有 -u,空变量不报错;因为没有 -e,上一步出错没停下来。加上这三行,相同场景会在变量赋值处立即报错退出。
怎么做:
#!/usr/bin/env bash
set -euo pipefail
# 之后的所有命令:任何一步失败即停止,未定义变量即报错
command || true 或 command || echo "可选步骤失败,继续" 显式豁免,不要关掉全局 -e。set 选项。规则: 引用任何变量时都用双引号:"$var"、"$@"、"${array[@]}";只在明确需要分词或通配符展开时才省略引号。
为什么: AI 写 bash 时很少给变量加引号,遇到含空格或通配符的路径时立刻出事。典型案例:cp $SRC $DST 在 SRC="/home/user/my files/data.txt" 时被 shell 解析为 cp /home/user/my files/data.txt $DST,变成三个参数,cp 报错或拷错文件。更危险的是 rm -rf $DIR/*,若 DIR 是 /tmp/app (带尾随空格),展开结果不可预料。
怎么做:
# 反例
cp $SRC $DST
rm -rf $DIR/*
# 正例
cp "$SRC" "$DST"
rm -rf "${DIR:?}/"* # :? 额外保证变量非空,空则报错退出
"${arr[@]}" 而非 ${arr[*]},保留每个元素的边界。output="$(some_command)"。规则: 执行 rm -rf、dd、mkfs、大范围覆盖等不可逆操作前,必须:① 用 ${VAR:?错误信息} 或显式 if [ -z "$VAR" ] 校验关键变量非空,② 检查路径符合预期(不是根目录、不是系统目录),③ 支持 DRY_RUN=1 模式只打印不执行。
为什么: AI 生成的清理脚本几乎从不做这类防御,使用者一旦环境变量配置错误,rm -rf "$DEPLOY_DIR/" 就会变成 rm -rf "/" 或 rm -rf "/var/" 并实际执行。这类事故在运维历史上反复出现,恢复成本极高。
怎么做:
#!/usr/bin/env bash
set -euo pipefail
DEPLOY_DIR="${DEPLOY_DIR:?必须设置 DEPLOY_DIR 环境变量}"
DRY_RUN="${DRY_RUN:-0}"
# 路径安全检查
if [[ "$DEPLOY_DIR" == "/" || "$DEPLOY_DIR" == "/usr" || "$DEPLOY_DIR" == "/etc" ]]; then
echo "❌ DEPLOY_DIR 疑似系统目录,拒绝执行" >&2
exit 1
fi
do_rm() {
if [[ "$DRY_RUN" == "1" ]]; then
echo "[DRY_RUN] rm -rf $1"
else
rm -rf "$1"
fi
}
do_rm "${DEPLOY_DIR}/old_release"
规则: 依赖外部命令前检查其是否存在(command -v);关键步骤打印清晰日志;捕获并展示有意义的错误信息,不让失败静默消失。
为什么: AI 生成的脚本常假设 jq、aws、kubectl 等工具已安装,在开发机上跑通了,在干净的 CI 容器或另一台服务器上立刻失败,且因为没有检查,报错信息是"command not found"而非"请先安装 jq"。加上静默管道失败(无 pipefail),真正的出错行往往被淹没。
怎么做:
#!/usr/bin/env bash
set -euo pipefail
# 前置依赖检查
for cmd in jq aws curl; do
if ! command -v "$cmd" &>/dev/null; then
echo "❌ 缺少依赖:$cmd,请先安装" >&2
exit 1
fi
done
# 关键步骤带日志
echo "🔄 开始上传到 S3..."
aws s3 sync ./dist "s3://${BUCKET_NAME}/" \
|| { echo "❌ S3 上传失败,退出码:$?" >&2; exit 1; }
echo "✅ 上传完成"
trap 'echo "脚本在第 $LINENO 行意外退出"' ERR 输出出错行号,方便定位。规则: 超过 50 行的脚本用函数组织,每个函数只做一件事;脚本入口校验参数数量和格式;业务逻辑复杂(JSON 处理、并发、错误恢复)时考虑改用 Python/Go,不要用 bash 硬扛。
为什么: AI 生成的长 bash 脚本常常是一整个线性流,几百行没有任何函数,全局变量满天飞,出错后根本无从定位。更隐蔽的问题:bash 的字符串处理、算术、数组在边界情况下行为出人意料,AI 很少把这些坑写进脚本注释,维护者往往在生产事故后才发现。
怎么做:
#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "用法: $0 <环境> <版本>" >&2
echo " 环境: staging | production" >&2
exit 1
}
# 参数校验
[[ $# -eq 2 ]] || usage
ENV="$1"
VERSION="$2"
[[ "$ENV" =~ ^(staging|production)$ ]] || { echo "❌ 无效环境: $ENV" >&2; usage; }
deploy() {
local env="$1" version="$2"
echo "部署 $version 到 $env..."
# ... 具体逻辑
}
deploy "$ENV" "$VERSION"
jq,不用 grep/sed 手撕;更复杂的改用 Python。#!/bin/bash
# 反例:没有 set -euo pipefail
TARGET=$1 # ❌ 无引号,无参数校验
BACKUP_DIR=/tmp/backup
mkdir $BACKUP_DIR
cp -r $TARGET $BACKUP_DIR # ❌ 路径含空格时出错
rm -rf $TARGET # ❌ TARGET 为空则 rm -rf ""(行为未定义)
echo "done" # 即使前面出错也会打印
#!/usr/bin/env bash
set -euo pipefail
trap 'echo "脚本在第 $LINENO 行意外退出" >&2' ERR
usage() { echo "用法: $0 <目标目录>" >&2; exit 1; }
[[ $# -eq 1 ]] || usage
TARGET="${1:?目标目录不能为空}" # ✅ 非空校验
DRY_RUN="${DRY_RUN:-0}"
BACKUP_DIR="/tmp/backup_$(date +%Y%m%d%H%M%S)"
# 路径合法性检查
[[ -d "$TARGET" ]] || { echo "❌ 目标目录不存在: $TARGET" >&2; exit 1; }
echo "备份目录: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR" # ✅ 变量加引号
cp -r "$TARGET" "$BACKUP_DIR/" # ✅
if [[ "$DRY_RUN" == "1" ]]; then
echo "[DRY_RUN] 不执行 rm,目标: $TARGET" # ✅ dry-run 保护
else
rm -rf "$TARGET"
fi
echo "完成"
set -euo pipefail(shebang 紧接其后)。"$var"),数组用 "${arr[@]}"。${VAR:?})和路径合法性检查。DRY_RUN 模式,或在危险步骤前有显式确认提示。command -v 提前检查,缺失时给出明确提示。