Bash开发专家
这个技能支持Bash脚本开发的最佳实践和安全标准。
🎯 核心规则
Shebang和安全性
- Shebang: 总是使用
#!/usr/bin/env bash - 设置选项: 总是使用
set -euo pipefail-e: 出错时退出-u: 未定义变量时退出-o pipefail: 如果任何命令失败,则管道失败
变量处理
- 引用: 总是引用变量
"${var}" - 常量: 使用大写字母表示全局/环境变量
- 局部变量: 使用小写字母表示函数局部变量
- 只读: 使用
readonly表示常量
函数最佳实践
- 局部变量: 总是使用
local关键字 - 参数验证: 验证必需的参数
- 返回代码: 成功为0,错误为非零
- 文档: 文档使用情况、描述和返回代码
📚 脚本模板
标准脚本结构
#!/usr/bin/env bash
set -euo pipefail
# 脚本元数据
# 使用: script_name.sh <arg1> [arg2]
# 描述: 这个脚本的作用
# 作者: 你的名字
# 版本: 1.0.0
# 全局常量(大写)
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
readonly VERSION="1.0.0"
# 输出的颜色代码
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # 无颜色
#######################################
# 显示使用信息
# 全局:
# SCRIPT_NAME
# 参数:
# 无
# 输出:
# 将使用信息写入stdout
#######################################
usage() {
cat <<EOF
使用方式: ${SCRIPT_NAME} <arg1> [arg2]
描述:
这个脚本详细做什么
参数:
arg1 必需参数描述
arg2 可选参数描述(默认: 值)
选项:
-h, --help 显示此帮助信息
-v, --version 显示版本信息
示例:
${SCRIPT_NAME} value1
${SCRIPT_NAME} value1 value2
EOF
}
#######################################
# 打印错误信息并退出
# 全局:
# RED, NC
# 参数:
# 错误信息
# 输出:
# 将错误写入stderr
# 返回:
# 1(错误代码)
#######################################
error() {
echo -e "${RED}错误: $*${NC}" >&2
exit 1
}
#######################################
# 打印信息消息
# 全局:
# GREEN, NC
# 参数:
# 信息消息
# 输出:
# 将消息写入stdout
#######################################
info() {
echo -e "${GREEN}信息: $*${NC}"
}
#######################################
# 打印警告消息
# 全局:
# YELLOW, NC
# 参数:
# 警告消息
# 输出:
# 将警告写入stdout
#######################################
warn() {
echo -e "${YELLOW}警告: $*${NC}"
}
#######################################
# 主函数
# 全局:
# 无
# 参数:
# 命令行参数
# 返回:
# 0成功,1错误
#######################################
main() {
local arg1="${1:?错误: arg1必需}"
local arg2="${2:-default_value}"
info "处理: ${arg1}"
# 你的逻辑在这里
info "成功完成"
return 0
}
# 错误处理程序
trap 'error "脚本在第$LINENO行失败"' ERR
# 解析参数
case "${1:-}" in
-h|--help)
usage
exit 0
;;
-v|--version)
echo "${SCRIPT_NAME} 版本 ${VERSION}"
exit 0
;;
esac
# 执行主函数
main "$@"
🛠️ 常见模式
错误处理
# 检查命令是否存在
if ! command -v git &> /dev/null; then
error "git未安装"
fi
# 检查文件是否存在
if [[ ! -f "${config_file}" ]]; then
error "配置文件未找到: ${config_file}"
fi
# 检查目录是否存在
if [[ ! -d "${target_dir}" ]]; then
mkdir -p "${target_dir}" || error "创建目录失败"
fi
输入验证
# 验证必需参数
validate_arg() {
local arg="${1:?错误: 参数必需}"
if [[ -z "${arg}" ]]; then
error "参数不能为空"
fi
}
# 验证数字
validate_number() {
local num="$1"
if ! [[ "${num}" =~ ^[0-9]+$ ]]; then
error "无效数字: ${num}"
fi
}
文件操作
# 安全文件读取
read_file() {
local file="$1"
if [[ ! -r "${file}" ]]; then
error "无法读取文件: ${file}"
fi
cat "${file}"
}
# 安全文件写入
write_file() {
local file="$1"
local content="$2"
echo "${content}" > "${file}" || error "写文件失败"
}
数组处理
# 声明数组
declare -a items=("item1" "item2" "item3")
# 遍历数组
for item in "${items[@]}"; do
echo "处理: ${item}"
done
# 数组长度
echo "总项目数: ${#items[@]}"
🎯 质量检查清单
在提交前检查这些:
- [ ] Shebang
#!/usr/bin/env bash存在 - [ ] 开头有
set -euo pipefail - [ ] 所有变量引用
"${var}" - [ ] 全局变量大写
- [ ] 局部变量使用
local关键字 - [ ] 函数有文档注释
- [ ] 实现了错误处理
- [ ] 提供了使用函数
- [ ] 退出代码有意义(0=成功,非零=错误)
- [ ] 脚本用
shellcheck测试过
🔍 常见反模式避免
❌ 不要:
# 未引用变量
cd $HOME/dir
# 缺少错误处理
mkdir /some/dir
# 未定义变量
echo $UNDEFINED_VAR
# 没有设置选项
#!/bin/bash
✅ 要:
# 引用变量
cd "${HOME}/dir" || error "目录更改失败"
# 带错误处理
mkdir -p "${target_dir}" || error "创建目录失败"
# 使用前检查
if [[ -n "${VAR:-}" ]]; then
echo "${VAR}"
fi
# 正确的设置选项
#!/usr/bin/env bash
set -euo pipefail
💡 测试
使用ShellCheck
# 安装shellcheck
brew install shellcheck # macOS
# 检查脚本
shellcheck script.sh
# 忽略特定警告
# shellcheck disable=SC2086
command ${unquoted}
测试函数
# 简单测试函数
test_function() {
local expected="expected_value"
local actual
actual="$(your_function)"
if [[ "${actual}" != "${expected}" ]]; then
error "测试失败: 预期 '${expected}', 实际 '${actual}'"
fi
info "测试通过"
}