关于 shell-scripting
shell-scripting 是一项编写可维护 Shell 脚本的技能,面向自动化命令行任务的开发者和运维人员。内容涵盖可移植性、错误处理、参数解析、常用工具集成,以及使用 ShellCheck 和 Bats 验证脚本。
主要功能
- 01POSIX sh 与 Bash 选择指南
- 02错误处理与清理模式
- 03短选项和长选项解析
- 04jq、yq 与文本工具示例
- 05ShellCheck 和 Bats 测试指南
适用场景
- 01自动化 CI/CD 流水线任务
- 02编写容器入口脚本
- 03创建备份与日志轮转任务
- 04构建项目脚本和测试运行器
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ancoleman/ ai-design-components --skill shell-scripting安装后在 Claude Code 中输入/shell-scripting确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
outputs.yamlexamples/error-handling.shgetopts-advanced.shgetopts-basic.shjson-yaml-processing.shlong-options.shproduction-template.shreferences/argument-parsing.mdcommon-utilities.mderror-handling.mdparameter-expansion.mdportability-guide.mdtesting-guide.mdscripts/lint-script.shtest-script.sh详细介绍
Shell 脚本
用途
介绍编写易于维护的 Shell 脚本的模式和最佳实践,涵盖错误处理、参数解析和可移植性方面的考量。内容包括如何选择 POSIX sh 或 Bash、参数展开、与常见工具(jq、yq、awk)集成,以及使用 ShellCheck 和 Bats 进行测试。
何时使用此技能
在以下场景中使用 Shell 脚本:
- 编排现有命令行工具和系统实用程序
- 编写 CI/CD 流水线脚本(GitHub Actions、GitLab CI)
- 创建容器入口点和初始化脚本
- 自动执行系统管理任务(备份、日志轮转)
- 构建开发工具(构建脚本、测试运行器)
在以下场景中考虑改用 Python/Go:
- 需要处理复杂的业务逻辑或数据结构
- 需要跨平台 GUI
- 需要大量集成 API(REST、gRPC)
- 脚本超过 200 行且逻辑复杂
POSIX sh 与 Bash
在以下场景中使用 POSIX sh(#!/bin/sh):
- 需要最大程度的可移植性(Linux、macOS、BSD、Alpine)
- 需要最小化容器镜像
- 用于嵌入式系统或目标环境未知
在以下场景中使用 Bash(#!/bin/bash):
- 环境受控(指定操作系统、容器)
- 需要数组或关联数组
- 高级参数展开能带来便利
- 进程替换
<(cmd)有用
如需详细的比较和测试策略,请参阅 references/portability-guide.md。
基本错误处理
快速失败模式
#!/bin/bash
set -euo pipefail
# -e: Exit on error
# -u: Exit on undefined variable
# -o pipefail: Pipeline fails if any command fails
适用于生产自动化、CI/CD 脚本和关键操作。
显式检查退出码
#!/bin/bash
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
exit 1
fi
适用于自定义错误消息和交互式脚本。
使用 Trap 处理程序进行清理
#!/bin/bash
set -euo pipefail
TEMP_FILE=$(mktemp)
cleanup() {
rm -f "$TEMP_FILE"
}
trap cleanup EXIT
适用于确保清理临时文件、锁和资源。
如需全面了解错误处理模式,请参阅 references/error-handling.md。
参数解析
使用 getopts 处理短选项(POSIX)
#!/bin/bash
while getopts "hvf:o:" opt; do
case "$opt" in
h) usage ;;
v) VERBOSE=true ;;
f) INPUT_FILE="$OPTARG" ;;
o) OUTPUT_FILE="$OPTARG" ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
长选项(手动解析)
#!/bin/bash
while [[ $# -gt 0 ]]; do
case "$1" in
--help) usage ;;
--verbose) VERBOSE=true; shift ;;
--file) INPUT_FILE="$2"; shift 2 ;;
--file=*) INPUT_FILE="${1#*=}"; shift ;;
*) break ;;
esac
done
如需了解混合处理方式和验证模式,请参阅 references/argument-parsing.md。
参数展开速查
# Default values
${var:-default} # Use default if unset
${var:=default} # Assign default if unset
: "${API_KEY:?Error: required}" # Error if unset
# String manipulation
${#var} # String length
${var:offset:length} # Substring
${var%.txt} # Remove suffix
${var##*/} # Basename
${var/old/new} # Replace first
${var//old/new} # Replace all
# Case conversion (Bash 4+)
${var^^} # Uppercase
${var,,} # Lowercase
如需了解完整的展开模式和数组处理,请参阅 references/parameter-expansion.md。
集成常见工具
使用 jq 处理 JSON
# Extract field
name=$(curl -sSL https://api.example.com/user | jq -r '.name')
# Filter array
active=$(jq '.users[] | select(.active) | .name' data.json)
# Check existence
if ! echo "$json" | jq -e '.field' >/dev/null; then
echo "Error: Field missing" >&2
fi
使用 yq 处理 YAML
# Read value (yq v4)
host=$(yq eval '.database.host' config.yaml)
# Update in-place
yq eval '.port = 5432' -i config.yaml
# Convert to JSON
yq eval -o=json config.yaml
文本处理
# awk: Extract columns
awk -F',' '{print $1, $3}' data.csv
# sed: Replace text
sed 's/old/new/g' file.txt
# grep: Pattern match
grep -E "ERROR|WARN" logfile.txt
如需详细示例和最佳实践,请参阅 references/common-utilities.md。
测试与验证
ShellCheck:静态分析
# Check script
shellcheck script.sh
# POSIX compliance
shellcheck --shell=sh script.sh
# Exclude warnings
shellcheck --exclude=SC2086 script.sh
Bats:自动化测试
#!/usr/bin/env bats
@test "script runs successfully" {
run ./script.sh --help
[ "$status" -eq 0 ]
[ "${lines[0]}" = "Usage: script.sh [OPTIONS]" ]
}
@test "handles missing argument" {
run ./script.sh
[ "$status" -eq 1 ]
[[ "$output" =~ "Error" ]]
}
运行测试:
bats test/
如需了解 CI/CD 集成和调试技巧,请参阅 references/testing-guide.md。
防御式编程检查清单
#!/bin/bash
set -euo pipefail
# Check required commands
command -v jq >/dev/null 2>&1 || {
echo "Error: jq required" >&2
exit 1
}
# Check environment variables
: "${API_KEY:?Error: API_KEY required}"
# Check files
[ -f "$CONFIG_FILE" ] || {
echo "Error: Config not found: $CONFIG_FILE" >&2
exit 1
}
# Quote all variables
echo "Processing: $file" # ❌ Unquoted
echo "Processing: \"$file\"" # ✅ Quoted
平台注意事项
macOS 与 Linux 的差异
# sed in-place
sed -i '' 's/old/new/g' file.txt # macOS
sed -i 's/old/new/g' file.txt # Linux
# Portable: Use temp file
sed 's/old/new/g' file.txt > file.txt.tmp
mv file.txt.tmp file.txt
# readlink
readlink -f /path # Linux only
cd "$(dirname "$0")" && pwd # Portable
如需了解完整的平台差异,请参阅 references/portability-guide.md。
脚本类别
系统管理: Cron 任务、日志轮转、备份自动化
构建/部署: CI/CD 流水线、Docker 构建、部署
开发工具: 项目设置、测试运行器、代码生成器
容器入口点: 初始化、信号处理、配置
生产脚本模板
#!/bin/bash
set -euo pipefail
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TEMP_DIR=""
cleanup() {
local exit_code=$?
rm -rf "$TEMP_DIR"
exit "$exit_code"
}
trap cleanup EXIT
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2
}
main() {
# Check dependencies
command -v jq >/dev/null 2>&1 || exit 1
# Parse arguments
# Validate input
# Process
# Report results
log "Completed successfully"
}
main "$@"
如需完整的生产环境模板,请参阅 examples/production-template.sh。
工具推荐
核心工具:
- jq:JSON 解析和转换
- yq:YAML 解析(推荐 v4)
- ShellCheck:静态分析和代码检查
- Bats:自动化测试框架
安装:
# macOS
brew install jq yq shellcheck bats-core
# Ubuntu/Debian
apt-get install jq shellcheck
相关技能
- linux-administration:系统命令和管理
- building-ci-pipelines:在 CI/CD 中使用脚本
- infrastructure-as-code:Terraform/Pulumi 封装脚本
- kubernetes-operations:kubectl 脚本、Helm 钩子
- writing-dockerfiles:容器入口点
附加资源
参考文件:
references/error-handling.md- 全面的错误处理模式references/argument-parsing.md- 高级解析技巧references/parameter-expansion.md- 完整的展开参考references/portability-guide.md- POSIX 与 Bash 的差异references/testing-guide.md- ShellCheck 和 Bats 指南references/common-utilities.md- jq、yq、awk、sed 的用法
示例脚本:
examples/production-template.sh- 可用于生产环境的模板examples/getopts-basic.sh- 简单的 getopts 用法examples/getopts-advanced.sh- 复杂的选项处理examples/long-options.sh- 手动解析长选项examples/error-handling.sh- 错误处理模式examples/json-yaml-processing.sh- jq/yq 示例
实用工具脚本:
scripts/lint-script.sh- 用于 CI 的 ShellCheck 包装器scripts/test-script.sh- 用于 CI 的 Bats 包装器