关于 bash-pro
面向 Bash 脚本编写、审查和加固的开发技能,涵盖安全参数处理、错误管理、可移植性和测试。适用于自动化、CI/CD 与运维脚本工作。
主要功能
- 01严格模式与错误处理
- 02安全参数解析和输入校验
- 03稳健文件与进程操作
- 04Bats 测试与 ShellCheck 静态分析
- 05跨平台兼容性指导
- 06日志、文档与 CI/CD 实践
适用场景
- 01编写自动化 Bash 脚本
- 02加固部署或运维脚本
- 03审查脚本输入与文件操作安全
- 04为脚本添加测试和 CI 检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rmyndharis/ antigravity-skills --skill bash-pro安装后在 Claude Code 中输入/bash-pro确认已加载。
详细介绍
何时使用此技能
- 为自动化、CI/CD 或运维编写或审查 Bash 脚本
- 加固 Shell 脚本以提升安全性和可移植性
何时不要使用此技能
- 你需要仅限 POSIX 的 Shell,不使用 Bash 特性
- 任务需要更高级的语言来处理复杂逻辑
- 你需要 Windows 原生脚本(PowerShell)
说明
- 定义脚本的输入、输出和失败模式。
- 应用严格模式和安全参数解析。
- 使用防御性模式实现核心逻辑。
- 使用 Bats 和 ShellCheck 添加测试和代码检查。
安全性
- 将输入视为不可信;避免 eval 和不安全的通配符展开。
- 在执行破坏性操作前优先使用试运行模式。
重点领域
- 具有严格错误处理的防御性编程
- POSIX 合规性和跨平台可移植性
- 安全的参数解析和输入验证
- 稳健的文件操作和临时资源管理
- 进程编排和管道安全
- 生产级日志记录和错误报告
- 使用 Bats 框架进行全面测试
- 使用 ShellCheck 进行静态分析,使用 shfmt 进行格式化
- 现代 Bash 5.x 特性和最佳实践
- CI/CD 集成和自动化工作流
方法
- 始终使用严格模式
set -Eeuo pipefail和适当的错误捕获 - 为所有变量展开添加引号,以防止单词拆分和通配符展开问题
- 优先使用数组和正确的迭代,而非
for f in $(ls)等不安全模式 - 使用
[[ ]]进行 Bash 条件判断,为 POSIX 合规性回退到[ ] - 使用
getopts和用法函数实现全面的参数解析 - 使用
mktemp和清理陷阱安全地创建临时文件和目录 - 优先使用
printf而非echo,以获得可预测的输出格式 - 使用命令替换
$()而非反引号,以提高可读性 - 实现带时间戳和可配置详细程度的结构化日志记录
- 将脚本设计为幂等并支持试运行模式
- 在 Bash 4.4+ 中使用
shopt -s inherit_errexit以实现更好的错误传播 - 使用
IFS=$'\n\t'防止对空格进行不必要的单词拆分 - 使用
: "${VAR:?message}"验证必需环境变量的输入 - 以
--结束选项解析,并使用rm -rf -- "$dir"进行安全操作 - 通过
set -x选择性启用--trace模式以进行详细调试 - 使用
xargs -0配合 NUL 边界进行安全的子进程编排 - 使用
readarray/mapfile从命令输出安全填充数组 - 实现稳健的脚本目录检测:
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" - 使用 NUL 安全模式:
find -print0 | while IFS= read -r -d '' file; do ...; done
兼容性与可移植性
- 使用
#!/usr/bin/env bashshebang 以实现跨系统可移植性 - 在脚本开头检查 Bash 版本:
(( BASH_VERSINFO[0] >= 4 && BASH_VERSINFO[1] >= 4 ))以使用 Bash 4.4+ 特性 - 验证所需外部命令存在:
command -v jq &>/dev/null || exit 1 - 检测平台差异:
case "$(uname -s)" in Linux*) ... ;; Darwin*) ... ;; esac - 处理 GNU 与 BSD 工具的差异(例如
sed -i与sed -i '') - 在所有目标平台(Linux、macOS、BSD 变体)上测试脚本
- 在脚本头部注释中记录最低版本要求
- 为平台特定功能提供回退实现
- 尽可能使用 Bash 内置特性而非外部命令,以提高可移植性
- 在需要 POSIX 合规性时避免使用 Bash 特有语法,使用 Bash 特定特性时加以说明
可读性与可维护性
- 在脚本中为清晰起见使用长格式选项:用
--verbose而不是-v - 采用一致的命名:函数/变量使用 snake_case,常量使用 UPPER_CASE
- 使用注释块添加章节标题,以组织相关函数
- 将函数保持在 50 行以内;将较大的函数重构为更小的组件
- 将相关函数分组在一起,并配上描述性的章节标题
- 使用能说明用途的描述性函数名:用
validate_input_file而不是check_file - 为非显而易见的逻辑添加行内注释,避免陈述显而易见的内容
- 保持一致的缩进(2 或 4 个空格,切勿将制表符与空格混用)
- 为保持一致,将左花括号放在同一行:
function_name() { - 使用空行分隔函数内的逻辑块
- 在头部注释中记录函数参数和返回值
- 将魔法数字和字符串提取为脚本顶部的具名常量
安全与安全模式
- 使用
readonly声明常量,以防止意外修改 - 为所有函数变量使用
local关键字,以避免污染全局作用域 - 为外部命令实现
timeout:timeout 30s curl ...可防止挂起 - 在操作前验证文件权限:
[[ -r "$file" ]] || exit 1 - 尽可能使用进程替换
<(command)而不是临时文件 - 在用于命令或文件操作之前,清理用户输入
- 使用模式匹配验证数字输入:
[[ $num =~ ^[0-9]+$ ]] - 切勿对用户输入使用
eval;使用数组进行动态命令构建 - 为敏感操作设置限制性的 umask:
(umask 077; touch "$secure_file") - 记录与安全相关的操作(身份验证、权限变更、文件访问)
- 使用
--将选项与参数分隔开:rm -rf -- "$user_input" - 在使用环境变量之前验证它们:
: "${REQUIRED_VAR:?not set}" - 显式检查所有安全关键操作的退出码
- 使用
trap确保即使异常退出也能执行清理
性能优化
- 避免在循环中使用子 shell;使用
while read而不是for i in $(cat file) - 优先使用 Bash 内建命令而非外部命令:用
[[ ]]而不是test,用${var//pattern/replacement}而不是sed - 批量操作而不是重复的单个操作(例如,一个带多个表达式的
sed) - 使用
mapfile/readarray从命令输出高效填充数组 - 避免重复的命令替换;将结果一次性存入变量
- 使用算术展开
$(( ))而不是expr进行计算 - 对于格式化输出,优先使用
printf而不是echo(更快且更可靠) - 使用关联数组进行查找,而不是重复 grep
- 对于大文件,逐行处理而不是将整个文件加载到内存中
- 当操作相互独立时,使用
xargs -P进行并行处理
文档标准
- 实现
--help和-h标志,显示用法、选项和示例 - 提供
--version标志,显示脚本版本和版权信息 - 在帮助输出中包含常见用例的使用示例
- 记录所有命令行选项及其用途说明
- 在用法消息中清晰列出必需与可选参数
- 记录退出码:0 表示成功,1 表示一般错误,特定失败使用特定代码
- 包含列出所需命令及版本的前提条件章节
- 添加头部注释块,包含脚本用途、作者和修改日期
- 记录脚本使用或需要的环境变量
- 在帮助中为常见问题提供故障排除章节
- 使用
shdoc从特殊注释格式生成文档 - 使用
shellman创建 man 手册页以便系统集成 - 为复杂脚本包含使用 Mermaid 或 GraphViz 绘制的架构图
现代 Bash 特性(5.x)
- Bash 5.0:关联数组改进,
${var@U}大写转换,${var@L}小写 - Bash 5.1:增强的
${parameter@operator}转换,用于兼容性的compatshopt 选项 - Bash 5.2:
varredir_close选项,改进的exec错误处理,EPOCHREALTIME微秒精度 - 在使用现代特性前检查版本:
[[ ${BASH_VERSINFO[0]} -ge 5 && ${BASH_VERSINFO[1]} -ge 2 ]] - 使用
${parameter@Q}输出 shell 引用的结果(Bash 4.4+) - 使用
${parameter@E}展开转义序列(Bash 4.4+) - 使用
${parameter@P}展开提示词(Bash 4.4+) - 使用
${parameter@A}输出赋值格式(Bash 4.4+) - 使用
wait -n等待任意后台任务(Bash 4.3+) - 使用
mapfile -d delim自定义分隔符(Bash 4.4+)
CI/CD 集成
- GitHub Actions:使用
shellcheck-problem-matchers实现内联注释 - Pre-commit 钩子:使用
shellcheck、shfmt、checkbashisms配置.pre-commit-config.yaml - 矩阵测试:在 Linux 和 macOS 上跨 Bash 4.4、5.0、5.1、5.2 进行测试
- 容器测试:使用官方 bash:5.2 Docker 镜像进行可复现的测试
- CodeQL:启用 shell 脚本扫描以发现安全漏洞
- Actionlint:验证使用 shell 脚本的 GitHub Actions 工作流文件
- 自动发布:自动打版本标签并生成变更日志
- 覆盖率报告:跟踪测试覆盖率并在出现回退时失败
- 示例工作流:
shellcheck *.sh && shfmt -d *.sh && bats test/
安全扫描与加固
- SAST:集成 Semgrep 并配置针对 shell 特定漏洞的自定义规则
- 密钥检测:使用
gitleaks或trufflehog防止凭据泄露 - 供应链:验证所引用外部脚本的校验和
- 沙箱化:在具有受限权限的容器中运行不受信任的脚本
- SBOM:记录依赖项和外部工具以满足合规要求
- 安全静态检查:启用面向安全的规则使用 ShellCheck
- 权限分析:审计脚本中不必要的 root/sudo 需求
- 输入清理:根据允许列表验证所有外部输入
- 审计日志:将所有与安全相关的操作记录到 syslog
- 容器安全:扫描脚本执行环境中的漏洞
可观测性与日志
- 结构化日志:输出 JSON 以供日志聚合系统使用
- 日志级别:实现 DEBUG、INFO、WARN、ERROR 并支持可配置的详细程度
- Syslog 集成:使用
logger命令集成系统日志 - 分布式追踪:添加 trace ID 以关联多脚本工作流
- 指标导出:输出 Prometheus 格式指标以供监控
- 错误上下文:在错误日志中包含堆栈跟踪、环境信息
- 日志轮转:为长时间运行的脚本配置日志文件轮转
- 性能指标:跟踪执行时间、资源使用、外部调用延迟
- 示例:
log_info() { logger -t "$SCRIPT_NAME" -p user.info "$*"; echo "[INFO] $*" >&2; }
质量检查清单
- 脚本以最少的抑制通过 ShellCheck 静态分析
- 代码使用 shfmt 以标准选项保持一致的格式
- 使用 Bats 实现全面的测试覆盖,包括边界情况
- 所有变量展开都正确加引号
- 错误处理覆盖所有失败模式并提供有意义的错误信息
- 临时资源通过 EXIT trap 正确清理
- 脚本支持
--help并提供清晰的用法信息 - 输入验证可防止注入攻击并处理边界情况
- 脚本可跨目标平台移植(Linux、macOS)
- 性能足以应对预期的工作负载和数据规模
输出
- 生产级 Bash 脚本,遵循防御性编程实践
- 使用 bats-core 或 shellspec 并结合 TAP 输出的全面测试套件
- 用于自动化测试的 CI/CD 流水线配置(GitHub Actions、GitLab CI)
- 使用 shdoc 生成的文档以及使用 shellman 生成的 man 手册页
- 具有可复用库函数和依赖管理的结构化项目布局
- 静态分析配置文件(.shellcheckrc、.shfmt.toml、.editorconfig)
- 针对关键工作流的性能基准测试和性能分析报告
- 包含 SAST、密钥扫描和漏洞报告的安全审查
- 具有跟踪模式、结构化日志和可观测性的调试实用工具
- 针对 Bash 3→5 升级和遗留系统现代化的迁移指南
- 包分发配置(Homebrew formula、deb/rpm 规范)
- 用于可复现执行环境的容器镜像
必备工具
静态分析与格式化
- ShellCheck:静态分析器,配置
enable=all和external-sources=true - shfmt:Shell 脚本格式化工具,使用标准配置(
-i 2 -ci -bn -sr -kp) - checkbashisms:检测 bash 特有的构造,用于可移植性分析
- Semgrep:SAST,提供针对 shell 特有安全问题的自定义规则
- CodeQL:GitHub 针对 shell 脚本的安全扫描
测试框架
- bats-core:Bats 的维护分支,具有现代特性和活跃开发
- shellspec:BDD 风格的测试框架,具有丰富的断言和 mocking 功能
- shunit2:针对 shell 脚本的 xUnit 风格测试框架
- bashing:具有 mocking 支持和测试隔离的测试框架
现代开发工具
- bashly:用于构建命令行应用的 CLI 框架生成器
- basher:用于依赖管理的 Bash 包管理器
- bpkg:具有类似 npm 接口的替代 bash 包管理器
- shdoc:从 shell 脚本注释生成 markdown 文档
- shellman:从 shell 脚本生成 man 手册页
CI/CD 与自动化
- pre-commit:多语言 pre-commit 钩子框架
- actionlint:GitHub Actions 工作流 linter
- gitleaks:密钥扫描,防止凭据泄露
- Makefile:用于 lint、format、test 和 release 工作流的自动化
应避免的常见陷阱
for f in $(ls ...)会导致分词/通配符错误(应使用find -print0 | while IFS= read -r -d '' f; do ...; done)- 未加引号的变量展开会导致意外行为
- 在复杂流程中依赖
set -e而没有适当的错误捕获 - 使用
echo输出数据(优先使用printf以确保可靠性) - 缺少针对临时文件和目录的清理 trap
- 不安全的数组填充(使用
readarray/mapfile而不是命令替换) - 忽略二进制安全的文件处理(文件名始终考虑 NUL 分隔符)
依赖管理
- 包管理器:使用
basher或bpkg安装 shell 脚本依赖 - Vendoring:将依赖复制到项目中以实现可复现构建
- 锁文件:记录所用依赖的确切版本
- 校验和验证:验证所引入外部脚本的完整性
- 版本固定:将依赖锁定到特定版本,以防止破坏性变更
- 依赖隔离:为不同的依赖集使用单独的目录
- 更新自动化:使用 Dependabot 或 Renovate 自动化依赖更新
- 安全扫描:扫描依赖中的已知漏洞
- 示例:
basher install username/repo@version或bpkg install username/repo -g
高级技巧
- 错误上下文:使用
trap 'echo "Error at line $LINENO: exit $?" >&2' ERR进行调试 - 安全处理临时文件:
trap 'rm -rf "$tmpdir"' EXIT; tmpdir=$(mktemp -d) - 版本检查:使用现代功能前,先检查
(( BASH_VERSINFO[0] >= 5 )) - 二进制安全数组:
readarray -d '' files < <(find . -print0) - 函数返回值:使用
declare -g result从函数返回复杂数据 - 关联数组:使用
declare -A config=([host]="localhost" [port]="8080")表示复杂数据结构 - 参数展开:
${filename%.sh}移除扩展名,${path##*/}获取基本名称,${text//old/new}替换所有匹配项 - 信号处理:使用
trap cleanup_function SIGHUP SIGINT SIGTERM实现优雅关闭 - 命令分组:
{ cmd1; cmd2; } > output.log共享重定向,( cd dir && cmd )使用子 shell 实现隔离 - 协程:
coproc proc { cmd; }; echo "data" >&"${proc[1]}"; read -u "${proc[0]}" result用于双向管道 - Here 文档:
cat <<-'EOF'中的-会移除前导制表符;引号可阻止展开 - 进程管理:使用
wait $pid等待后台任务,使用jobs -p列出后台进程 ID - 条件执行:
cmd1 && cmd2仅当 cmd1 成功时才运行 cmd2,cmd1 || cmd2在 cmd1 失败时运行 cmd2 - 花括号展开:
touch file{1..10}.txt可高效创建多个文件 - 名称引用变量:
declare -n ref=varname创建对另一个变量的引用(Bash 4.3+) - 改进错误捕获:使用
set -Eeuo pipefail; shopt -s inherit_errexit实现全面的错误处理 - 并行执行:使用
xargs -P $(nproc) -n 1 command,根据 CPU 核心数并行处理 - 结构化输出:使用
jq -n --arg key "$value" '{key: $key}'生成 JSON - 性能分析:使用
time -v查看详细资源使用情况,或使用TIMEFORMAT自定义计时
参考资料与延伸阅读
风格指南与最佳实践
- Google Shell 风格指南 - 全面的风格指南,涵盖引用、数组以及何时使用 shell
- Bash 常见陷阱 - 常见 Bash 错误汇总及避免方法
- Bash Hackers Wiki - 全面的 Bash 文档与高级技巧
- 防御式 BASH 编程 - 现代防御式编程模式
工具与框架
- ShellCheck - 静态分析工具,附带详尽的 Wiki 文档
- shfmt - Shell 脚本格式化工具,附带详细的标志说明
- bats-core - 持续维护的 Bash 测试框架
- shellspec - 面向 shell 脚本的 BDD 风格测试框架
- bashly - 现代 Bash CLI 框架生成器
- shdoc - Shell 脚本文档生成器
安全与高级主题
- Bash 安全最佳实践 - 注重安全性的 shell 脚本模式
- Awesome Bash - 精选的 Bash 资源与工具列表
- Pure Bash Bible - 纯 Bash 替代外部命令的方案集
评论
支持 Markdown