shell-scripting
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseShell Scripting
Shell脚本编写
Purpose
用途
Provides patterns and best practices for writing maintainable shell scripts with error handling, argument parsing, and portability considerations. Covers POSIX sh vs Bash decision-making, parameter expansion, integration with common utilities (jq, yq, awk), and testing with ShellCheck and Bats.
提供编写可维护Shell脚本的模式与最佳实践,涵盖错误处理、参数解析和可移植性考量。包括POSIX sh与Bash的选择决策、参数扩展、与常用工具(jq、yq、awk)的集成,以及使用ShellCheck和Bats进行测试的方法。
When to Use This Skill
适用场景
Use shell scripting when:
- Orchestrating existing command-line tools and system utilities
- Writing CI/CD pipeline scripts (GitHub Actions, GitLab CI)
- Creating container entrypoints and initialization scripts
- Automating system administration tasks (backups, log rotation)
- Building development tooling (build scripts, test runners)
Consider Python/Go instead when:
- Complex business logic or data structures required
- Cross-platform GUI needed
- Heavy API integration (REST, gRPC)
- Script exceeds 200 lines with significant logic complexity
在以下场景中使用Shell脚本:
- 编排现有命令行工具与系统实用程序
- 编写CI/CD流水线脚本(GitHub Actions、GitLab CI)
- 创建容器入口点与初始化脚本
- 自动化系统管理任务(备份、日志轮转)
- 构建开发工具链(构建脚本、测试运行器)
在以下场景中考虑使用Python/Go替代:
- 需要复杂业务逻辑或数据结构
- 需要跨平台GUI
- 大量API集成(REST、gRPC)
- 脚本逻辑复杂度高且代码量超过200行
POSIX sh vs Bash
POSIX sh 与 Bash
Use POSIX sh (#!/bin/sh) when:
- Maximum portability required (Linux, macOS, BSD, Alpine)
- Minimal container images needed
- Embedded systems or unknown target environments
Use Bash (#!/bin/bash) when:
- Controlled environment (specific OS, container)
- Arrays or associative arrays needed
- Advanced parameter expansion beneficial
- Process substitution useful
<(cmd)
For detailed comparison and testing strategies, see .
references/portability-guide.md选择POSIX sh(#!/bin/sh)的场景:
- 需要最大程度的可移植性(Linux、macOS、BSD、Alpine)
- 需要最小化容器镜像
- 嵌入式系统或目标环境未知
选择Bash(#!/bin/bash)的场景:
- 受控环境(特定操作系统、容器)
- 需要数组或关联数组
- 高级参数扩展能带来便利
- 进程替换有用
<(cmd)
如需详细对比与测试策略,请参阅。
references/portability-guide.mdEssential Error Handling
核心错误处理
Fail-Fast Pattern
快速失败模式
bash
#!/bin/bash
set -euo pipefailbash
#!/bin/bash
set -euo pipefail-e: Exit on error
-e: 遇到错误时退出
-u: Exit on undefined variable
-u: 遇到未定义变量时退出
-o pipefail: Pipeline fails if any command fails
-o pipefail: 管道中任意命令失败则整个管道失败
Use for production automation, CI/CD scripts, and critical operations.
适用于生产自动化、CI/CD脚本和关键操作场景。Explicit Exit Code Checking
显式退出码检查
bash
#!/bin/bash
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
exit 1
fiUse for custom error messages and interactive scripts.
bash
#!/bin/bash
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
exit 1
fi适用于自定义错误消息和交互式脚本。
Trap Handlers for Cleanup
清理操作的陷阱处理器
bash
#!/bin/bash
set -euo pipefail
TEMP_FILE=$(mktemp)
cleanup() {
rm -f "$TEMP_FILE"
}
trap cleanup EXITUse for guaranteed cleanup of temporary files, locks, and resources.
For comprehensive error patterns, see .
references/error-handling.mdbash
#!/bin/bash
set -euo pipefail
TEMP_FILE=$(mktemp)
cleanup() {
rm -f "$TEMP_FILE"
}
trap cleanup EXIT用于保证临时文件、锁和资源的清理。
如需完整的错误处理模式,请参阅。
references/error-handling.mdArgument Parsing
参数解析
Short Options with getopts (POSIX)
使用getopts实现短选项(POSIX兼容)
bash
#!/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))bash
#!/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))Long Options (Manual Parsing)
长选项(手动解析)
bash
#!/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
doneFor hybrid approaches and validation patterns, see .
references/argument-parsing.mdbash
#!/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.mdParameter Expansion Quick Reference
参数扩展速查
bash
undefinedbash
undefinedDefault values
默认值
${var:-default} # Use default if unset
${var:=default} # Assign default if unset
: "${API_KEY:?Error: required}" # Error if unset
${var:-default} # 变量未设置时使用默认值
${var:=default} # 变量未设置时赋值默认值
: "${API_KEY:?Error: required}" # 变量未设置时抛出错误
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
${#var} # 字符串长度
${var:offset:length} # 子字符串
${var%.txt} # 移除后缀
${var##*/} # 获取文件名
${var/old/new} # 替换第一个匹配项
${var//old/new} # 替换所有匹配项
Case conversion (Bash 4+)
大小写转换(Bash 4+)
${var^^} # Uppercase
${var,,} # Lowercase
For complete expansion patterns and array handling, see `references/parameter-expansion.md`.${var^^} # 转换为大写
${var,,} # 转换为小写
如需完整的扩展模式和数组处理方法,请参阅`references/parameter-expansion.md`。Common Utilities Integration
常用工具集成
JSON with jq
使用jq处理JSON
bash
undefinedbash
undefinedExtract field
提取字段
name=$(curl -sSL https://api.example.com/user | jq -r '.name')
name=$(curl -sSL https://api.example.com/user | jq -r '.name')
Filter array
过滤数组
active=$(jq '.users[] | select(.active) | .name' data.json)
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
undefinedif ! echo "$json" | jq -e '.field' >/dev/null; then
echo "Error: Field missing" >&2
fi
undefinedYAML with yq
使用yq处理YAML
bash
undefinedbash
undefinedRead value (yq v4)
读取值(yq v4)
host=$(yq eval '.database.host' config.yaml)
host=$(yq eval '.database.host' config.yaml)
Update in-place
原地更新
yq eval '.port = 5432' -i config.yaml
yq eval '.port = 5432' -i config.yaml
Convert to JSON
转换为JSON
yq eval -o=json config.yaml
undefinedyq eval -o=json config.yaml
undefinedText Processing
文本处理
bash
undefinedbash
undefinedawk: Extract columns
awk: 提取列
awk -F',' '{print $1, $3}' data.csv
awk -F',' '{print $1, $3}' data.csv
sed: Replace text
sed: 替换文本
sed 's/old/new/g' file.txt
sed 's/old/new/g' file.txt
grep: Pattern match
grep: 模式匹配
grep -E "ERROR|WARN" logfile.txt
For detailed examples and best practices, see `references/common-utilities.md`.grep -E "ERROR|WARN" logfile.txt
如需详细示例和最佳实践,请参阅`references/common-utilities.md`。Testing and Validation
测试与验证
ShellCheck: Static Analysis
ShellCheck:静态分析
bash
undefinedbash
undefinedCheck script
检查脚本
shellcheck script.sh
shellcheck script.sh
POSIX compliance
检查POSIX合规性
shellcheck --shell=sh script.sh
shellcheck --shell=sh script.sh
Exclude warnings
排除指定警告
shellcheck --exclude=SC2086 script.sh
undefinedshellcheck --exclude=SC2086 script.sh
undefinedBats: Automated Testing
Bats:自动化测试
bash
#!/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" ]]
}Run tests:
bash
bats test/For CI/CD integration and debugging techniques, see .
references/testing-guide.mdbash
#!/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" ]]
}运行测试:
bash
bats test/如需CI/CD集成和调试技巧,请参阅。
references/testing-guide.mdDefensive Programming Checklist
防御式编程检查清单
bash
#!/bin/bash
set -euo pipefailbash
#!/bin/bash
set -euo pipefailCheck required commands
检查依赖命令是否存在
command -v jq >/dev/null 2>&1 || {
echo "Error: jq required" >&2
exit 1
}
command -v jq >/dev/null 2>&1 || {
echo "Error: jq required" >&2
exit 1
}
Check environment variables
检查环境变量
: "${API_KEY:?Error: API_KEY required}"
: "${API_KEY:?Error: API_KEY required}"
Check files
检查文件是否存在
[ -f "$CONFIG_FILE" ] || {
echo "Error: Config not found: $CONFIG_FILE" >&2
exit 1
}
[ -f "$CONFIG_FILE" ] || {
echo "Error: Config not found: $CONFIG_FILE" >&2
exit 1
}
Quote all variables
为所有变量添加引号
echo "Processing: $file" # ❌ Unquoted
echo "Processing: "$file"" # ✅ Quoted
undefinedecho "Processing: $file" # ❌ 未加引号
echo "Processing: "$file"" # ✅ 已加引号
undefinedPlatform Considerations
平台兼容性考量
macOS vs Linux Differences
macOS与Linux的差异
bash
undefinedbash
undefinedsed in-place
sed原地修改
sed -i '' 's/old/new/g' file.txt # macOS
sed -i 's/old/new/g' file.txt # Linux
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
sed 's/old/new/g' file.txt > file.txt.tmp
mv file.txt.tmp file.txt
readlink
readlink命令
readlink -f /path # Linux only
cd "$(dirname "$0")" && pwd # Portable
For complete platform differences, see `references/portability-guide.md`.readlink -f /path # 仅Linux支持
cd "$(dirname "$0")" && pwd # 可移植方案
如需完整的平台差异说明,请参阅`references/portability-guide.md`。Script Categories
脚本分类
System Administration: Cron jobs, log rotation, backup automation
Build/Deployment: CI/CD pipelines, Docker builds, deployments
Development Tooling: Project setup, test runners, code generators
Container Entrypoints: Initialization, signal handling, configuration
系统管理类: 定时任务、日志轮转、备份自动化
构建/部署类: CI/CD流水线、Docker构建、部署脚本
开发工具类: 项目初始化、测试运行器、代码生成器
容器入口点类: 初始化、信号处理、配置脚本
Production Script Template
生产级脚本模板
bash
#!/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 "$@"For complete production template, see .
examples/production-template.shbash
#!/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() {
# 检查依赖
command -v jq >/dev/null 2>&1 || exit 1
# 解析参数
# 验证输入
# 处理逻辑
# 输出结果
log "Completed successfully"
}
main "$@"如需完整的生产级模板,请参阅。
examples/production-template.shTool Recommendations
工具推荐
Core Tools:
- jq: JSON parsing and transformation
- yq: YAML parsing (v4 recommended)
- ShellCheck: Static analysis and linting
- Bats: Automated testing framework
Installation:
bash
undefined核心工具:
- jq:JSON解析与转换
- yq:YAML解析(推荐v4版本)
- ShellCheck:静态分析与代码检查
- Bats:自动化测试框架
安装方法:
bash
undefinedmacOS
macOS
brew install jq yq shellcheck bats-core
brew install jq yq shellcheck bats-core
Ubuntu/Debian
Ubuntu/Debian
apt-get install jq shellcheck
undefinedapt-get install jq shellcheck
undefinedRelated Skills
相关技能
- linux-administration: System commands and administration
- building-ci-pipelines: Using scripts in CI/CD
- infrastructure-as-code: Terraform/Pulumi wrappers
- kubernetes-operations: kubectl scripts, Helm hooks
- writing-dockerfiles: Container entrypoints
- linux-administration:系统命令与管理
- building-ci-pipelines:在CI/CD中使用脚本
- infrastructure-as-code:Terraform/Pulumi包装器
- kubernetes-operations:kubectl脚本、Helm钩子
- writing-dockerfiles:容器入口点编写
Additional Resources
额外资源
Reference Files:
- - Comprehensive error patterns
references/error-handling.md - - Advanced parsing techniques
references/argument-parsing.md - - Complete expansion reference
references/parameter-expansion.md - - POSIX vs Bash differences
references/portability-guide.md - - ShellCheck and Bats guide
references/testing-guide.md - - jq, yq, awk, sed usage
references/common-utilities.md
Example Scripts:
- - Production-ready template
examples/production-template.sh - - Simple getopts usage
examples/getopts-basic.sh - - Complex option handling
examples/getopts-advanced.sh - - Manual long option parsing
examples/long-options.sh - - Error handling patterns
examples/error-handling.sh - - jq/yq examples
examples/json-yaml-processing.sh
Utility Scripts:
- - ShellCheck wrapper for CI
scripts/lint-script.sh - - Bats wrapper for CI
scripts/test-script.sh
参考文档:
- - 完整的错误处理模式
references/error-handling.md - - 高级参数解析技巧
references/argument-parsing.md - - 完整的参数扩展参考
references/parameter-expansion.md - - POSIX与Bash的差异说明
references/portability-guide.md - - ShellCheck与Bats使用指南
references/testing-guide.md - - jq、yq、awk、sed使用方法
references/common-utilities.md
示例脚本:
- - 生产级脚本模板
examples/production-template.sh - - getopts基础用法示例
examples/getopts-basic.sh - - 复杂选项处理示例
examples/getopts-advanced.sh - - 手动长选项解析示例
examples/long-options.sh - - 错误处理模式示例
examples/error-handling.sh - - jq/yq使用示例
examples/json-yaml-processing.sh
实用脚本:
- - 用于CI的ShellCheck包装器
scripts/lint-script.sh - - 用于CI的Bats包装器
scripts/test-script.sh