bash-master
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBash Scripting Mastery
Bash脚本精通指南
🚨 CRITICAL GUIDELINES
🚨 重要指南
Windows File Path Requirements
Windows文件路径要求
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes () in file paths, NOT forward slashes ().
\/Examples:
- ❌ WRONG:
D:/repos/project/file.tsx - ✅ CORRECT:
D:\repos\project\file.tsx
This applies to:
- Edit tool file_path parameter
- Write tool file_path parameter
- All file operations on Windows systems
强制要求:在Windows系统中使用文件路径时必须使用反斜杠()
\在Windows系统中使用编辑或写入工具时,文件路径必须使用反斜杠(),不能使用正斜杠()。
\/示例:
- ❌ 错误:
D:/repos/project/file.tsx - ✅ 正确:
D:\repos\project\file.tsx
此要求适用于:
- 编辑工具的file_path参数
- 写入工具的file_path参数
- Windows系统上的所有文件操作
Documentation Guidelines
文档指南
NEVER create new documentation files unless explicitly requested by the user.
- Priority: Update existing README.md files rather than creating new documentation
- Repository cleanliness: Keep repository root clean - only README.md unless user requests otherwise
- Style: Documentation should be concise, direct, and professional - avoid AI-generated tone
- User preference: Only create additional .md files when user specifically asks for documentation
Comprehensive guide for writing professional, portable, and maintainable bash scripts across all platforms.
除非用户明确要求,否则绝不创建新的文档文件。
- 优先级:优先更新现有README.md文件,而非创建新文档
- 仓库整洁性:保持仓库根目录整洁 - 除非用户要求,否则仅保留README.md
- 风格:文档应简洁、直接、专业 - 避免AI生成的语气
- 用户偏好:仅在用户明确要求文档时才创建额外的.md文件
跨全平台编写专业、可移植且易于维护的Bash脚本综合指南。
TL;DR QUICK REFERENCE
TL;DR 快速参考
Essential Checklist for Every Bash Script:
bash
#!/usr/bin/env bash
set -euo pipefail # Exit on error, undefined vars, pipe failures
IFS=$'\n\t' # Safe word splitting每个Bash脚本必备检查清单:
bash
#!/usr/bin/env bash
set -euo pipefail # 遇到错误、未定义变量或管道失败时退出
IFS=$'\n\t' # 安全的单词拆分Use: shellcheck your_script.sh before deployment
部署前使用:shellcheck your_script.sh
Test on target platform(s) before production
生产前在目标平台上测试
**Platform Compatibility Quick Check:**
```bash
**平台兼容性快速检查:**
```bashLinux/macOS: ✓ Full bash features
Linux/macOS: ✓ 支持全部Bash特性
Git Bash (Windows): ✓ Most features, ✗ Some system calls
Git Bash (Windows): ✓ 支持大部分特性,✗ 部分系统调用不支持
Containers: ✓ Depends on base image
容器: ✓ 取决于基础镜像
POSIX mode: Use /bin/sh and avoid bashisms
POSIX模式: 使用/bin/sh并避免Bash特有语法
---
---Overview
概述
This skill provides expert bash/shell scripting knowledge for ANY scripting task, ensuring professional-grade quality across all platforms.
MUST use this skill for:
- ✅ ANY bash/shell script creation or modification
- ✅ System automation and tooling
- ✅ DevOps/CI/CD pipeline scripts
- ✅ Build and deployment automation
- ✅ Script review, debugging, or optimization
- ✅ Converting manual commands to automated scripts
- ✅ Cross-platform script compatibility
What this skill provides:
- Google Shell Style Guide compliance - Industry-standard formatting and patterns
- ShellCheck validation - Automatic detection of common issues
- Cross-platform compatibility - Linux, macOS, Windows (Git Bash/WSL), containers
- POSIX compliance - Portable scripts that work everywhere
- Security hardening - Input validation, injection prevention, privilege management
- Error handling - Robust , trap handlers, exit codes
set -euo pipefail - Performance optimization - Efficient patterns, avoiding anti-patterns
- Testing with BATS - Unit testing, integration testing, CI/CD integration
- Debugging techniques - Logging, troubleshooting, profiling
- Production-ready patterns - Templates and best practices for real-world use
This skill activates automatically for:
- Any mention of "bash", "shell", "script" in task
- System automation requests
- DevOps/CI/CD tasks
- Build/deployment automation
- Command line tool creation
本技能为任何脚本任务提供专业的Bash/Shell脚本知识,确保跨所有平台的专业级质量。
必须使用本技能的场景:
- ✅ 任何Bash/Shell脚本的创建或修改
- ✅ 系统自动化与工具开发
- ✅ DevOps/CI/CD流水线脚本
- ✅ 构建与部署自动化
- ✅ 脚本审核、调试或优化
- ✅ 将手动命令转换为自动化脚本
- ✅ 跨平台脚本兼容性处理
本技能提供的能力:
- 符合Google Shell风格指南 - 行业标准的格式与模式
- ShellCheck校验 - 自动检测常见问题
- 跨平台兼容性 - 支持Linux、macOS、Windows(Git Bash/WSL)、容器
- POSIX合规 - 可在所有环境运行的可移植脚本
- 安全加固 - 输入验证、注入防护、权限管理
- 错误处理 - 健壮的、陷阱处理器、退出码
set -euo pipefail - 性能优化 - 高效模式,避免反模式
- 基于BATS的测试 - 单元测试、集成测试、CI/CD集成
- 调试技巧 - 日志、故障排查、性能分析
- 生产就绪模式 - 适用于实际场景的模板与最佳实践
本技能自动激活的场景:
- 任务中提及"bash"、"shell"、"script"
- 系统自动化请求
- DevOps/CI/CD任务
- 构建/部署自动化
- 命令行工具创建
Core Principles
核心原则
1. Safety First
1. 安全优先
ALWAYS start scripts with safety settings:
bash
#!/usr/bin/env bash所有脚本必须以安全设置开头:
bash
#!/usr/bin/env bashFail fast and loud
快速且明确地失败
set -e # Exit on any error
set -u # Exit on undefined variable
set -o pipefail # Exit on pipe failure
set -E # ERR trap inherited by functions
set -e # 遇到任何错误时退出
set -u # 遇到未定义变量时退出
set -o pipefail # 管道失败时退出
set -E # ERR陷阱被函数继承
Optionally:
可选:
set -x # Debug mode (print commands before execution)
set -x # 调试模式(执行前打印命令)
set -C # Prevent file overwrites with redirection
set -C # 防止重定向覆盖文件
Safe word splitting
安全的单词拆分
IFS=$'\n\t'
IFS=$'\n\t'
Script metadata
脚本元数据
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
**Why this matters:**
- `set -e`: Prevents cascading failures
- `set -u`: Catches typos in variable names
- `set -o pipefail`: Catches failures in the middle of pipes
- `IFS=$'\n\t'`: Prevents word splitting on spaces (security issue)readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
**为什么这很重要:**
- `set -e`: 防止故障扩散
- `set -u`: 捕获变量名拼写错误
- `set -o pipefail`: 捕获管道中间环节的失败
- `IFS=$'\n\t'`: 防止空格导致的单词拆分(安全问题)2. POSIX Compatibility vs Bash Features
2. POSIX兼容性 vs Bash特性
Know when to use which:
bash
undefined了解何时使用哪种方式:
bash
undefinedPOSIX-compliant (portable across shells)
符合POSIX标准(跨Shell可移植)
#!/bin/sh
#!/bin/sh
Use: [ ] tests, no arrays, no [[ ]], no <(process substitution)
使用: [ ] 测试,不使用数组,不使用[[ ]],不使用<(进程替换)
Bash-specific (modern features, clearer syntax)
Bash特有(现代特性,语法更清晰)
#!/usr/bin/env bash
#!/usr/bin/env bash
Use: [[ ]], arrays, associative arrays, <(), process substitution
使用: [[ ]]、数组、关联数组、<()、进程替换
**Decision matrix:**
- Need to run on any UNIX system → Use `#!/bin/sh` and POSIX only
- Control the environment (modern Linux/macOS) → Use `#!/usr/bin/env bash`
- Need advanced features (arrays, regex) → Use `#!/usr/bin/env bash`
**决策矩阵:**
- 需要在任何UNIX系统运行 → 使用`#!/bin/sh`且仅使用POSIX语法
- 控制运行环境(现代Linux/macOS) → 使用`#!/usr/bin/env bash`
- 需要高级特性(数组、正则) → 使用`#!/usr/bin/env bash`3. Quoting Rules (Critical)
3. 引用规则(至关重要)
bash
undefinedbash
undefinedALWAYS quote variables to prevent word splitting and globbing
始终引用变量以防止单词拆分和通配符扩展
bad_cmd=$file_path # ✗ WRONG - word splitting
good_cmd="$file_path" # ✓ CORRECT
bad_cmd=$file_path # ✗ 错误 - 单词拆分
good_cmd="$file_path" # ✓ 正确
Arrays: Quote expansion
数组:引用扩展
files=("file 1.txt" "file 2.txt")
process "${files[@]}" # ✓ CORRECT - each element quoted
process "${files[*]}" # ✗ WRONG - all elements as one string
files=("file 1.txt" "file 2.txt")
process "${files[@]}" # ✓ 正确 - 每个元素都被引用
process "${files[*]}" # ✗ 错误 - 所有元素作为单个字符串
Command substitution: Quote the result
命令替换:引用结果
result="$(command)" # ✓ CORRECT
result=$(command) # ✗ WRONG (unless you want word splitting)
result="$(command)" # ✓ 正确
result=$(command) # ✗ 错误(除非你希望单词拆分)
Exception: When you WANT word splitting
例外:当你确实需要单词拆分时
shellcheck disable=SC2086
shellcheck disable=SC2086
flags="-v -x -z"
command $flags # Intentional word splitting
undefinedflags="-v -x -z"
command $flags # 有意的单词拆分
undefined4. Use ShellCheck
4. 使用ShellCheck
ALWAYS run ShellCheck before deployment:
bash
undefined部署前必须运行ShellCheck:
bash
undefinedInstall
安装
Ubuntu/Debian: apt-get install shellcheck
Ubuntu/Debian: apt-get install shellcheck
macOS: brew install shellcheck
macOS: brew install shellcheck
Windows: scoop install shellcheck
Windows: scoop install shellcheck
Usage
使用方法
shellcheck your_script.sh
shellcheck -x your_script.sh # Follow source statements
shellcheck your_script.sh
shellcheck -x your_script.sh # 跟踪源语句
In CI/CD
在CI/CD中使用
find . -name "*.sh" -exec shellcheck {} +
**ShellCheck catches:**
- Quoting issues
- Bashisms in POSIX scripts
- Common logic errors
- Security vulnerabilities
- Performance anti-patterns
---find . -name "*.sh" -exec shellcheck {} +
**ShellCheck可检测:**
- 引用问题
- POSIX脚本中的Bash特有语法
- 常见逻辑错误
- 安全漏洞
- 性能反模式
---Platform-Specific Considerations
平台特定注意事项
Windows (Git Bash) Path Conversion - CRITICAL
Windows (Git Bash) 路径转换 - 至关重要
ESSENTIAL KNOWLEDGE: Git Bash/MINGW automatically converts Unix-style paths to Windows paths. This is the most common source of cross-platform scripting errors on Windows.
Complete Guide: See for comprehensive documentation.
references/windows-git-bash-paths.mdQuick Reference:
bash
undefined必备知识: Git Bash/MINGW会自动将Unix风格路径转换为Windows路径。这是Windows系统上跨平台脚本错误的最常见来源。
完整指南: 参阅获取全面文档。
references/windows-git-bash-paths.md快速参考:
bash
undefinedAutomatic conversion happens for:
自动转换的场景:
/foo → C:/Program Files/Git/usr/foo
--dir=/tmp → --dir=C:/msys64/tmp
/foo → C:/Program Files/Git/usr/foo
--dir=/tmp → --dir=C:/msys64/tmp
Disable conversion when needed
需要时禁用转换
MSYS_NO_PATHCONV=1 command /path/that/should/not/convert
MSYS_NO_PATHCONV=1 command /path/that/should/not/convert
Manual conversion with cygpath
使用cygpath手动转换
unix_path=$(cygpath -u "C:\Windows\System32") # Windows to Unix
win_path=$(cygpath -w "/c/Users/username") # Unix to Windows
unix_path=$(cygpath -u "C:\Windows\System32") # Windows转Unix
win_path=$(cygpath -w "/c/Users/username") # Unix转Windows
Shell detection (fastest method)
Shell检测(最快方法)
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "mingw"* ]]; then
echo "Git Bash detected"
# Use path conversion
fi
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "mingw"* ]]; then
echo "检测到Git Bash"
# 使用路径转换
fi
Or check $MSYSTEM variable (Git Bash/MSYS2 specific)
或者检查$MSYSTEM变量(Git Bash/MSYS2特有)
case "${MSYSTEM:-}" in
MINGW64|MINGW32|MSYS)
echo "MSYS2/Git Bash environment: $MSYSTEM"
;;
esac
**Common Issues:**
```bashcase "${MSYSTEM:-}" in
MINGW64|MINGW32|MSYS)
echo "MSYS2/Git Bash环境: $MSYSTEM"
;;
esac
**常见问题:**
```bashProblem: Flags converted to paths
问题:标志被转换为路径
command /e /s # /e becomes C:/Program Files/Git/e
command /e /s # /e 变为 C:/Program Files/Git/e
Solution: Use double slashes or dashes
解决方案:使用双斜杠或短横线
command //e //s # OR: command -e -s
command //e //s # 或者: command -e -s
Problem: Spaces in paths
问题:路径中包含空格
cd C:\Program Files\Git # Fails
cd C:\Program Files\Git # 失败
Solution: Quote paths
解决方案:引用路径
cd "C:\Program Files\Git" # OR: cd /c/Program\ Files/Git
undefinedcd "C:\Program Files\Git" # 或者: cd /c/Program\ Files/Git
undefinedLinux
Linux
Primary target for most bash scripts:
bash
undefined大多数Bash脚本的主要目标平台:
bash
undefinedLinux-specific features available
Linux特有的可用特性
/proc filesystem
systemd integration
Linux-specific commands (apt, yum, systemctl)
/proc文件系统
systemd集成
Linux特有命令(apt、yum、systemctl)
Check for Linux
检测Linux
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
# Linux-specific code
fi
undefinedif [[ "$OSTYPE" == "linux-gnu"* ]]; then
# Linux特有代码
fi
undefinedmacOS
macOS
BSD-based utilities (different from GNU):
bash
undefined基于BSD的工具(与GNU不同):
bash
undefinedmacOS differences
macOS差异
sed -i '' # macOS requires empty string
sed -i # Linux doesn't need it
sed -i '' # macOS需要空字符串
sed -i # Linux不需要
Use ggrep, gsed, etc. for GNU versions
使用ggrep、gsed等获取GNU版本
if command -v gsed &> /dev/null; then
SED=gsed
else
SED=sed
fi
if command -v gsed &> /dev/null; then
SED=gsed
else
SED=sed
fi
Check for macOS
检测macOS
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS-specific code
fi
undefinedif [[ "$OSTYPE" == "darwin"* ]]; then
# macOS特有代码
fi
undefinedWindows (Git Bash / WSL)
Windows (Git Bash / WSL)
Git Bash limitations:
bash
undefinedGit Bash限制:
bash
undefinedAvailable in Git Bash:
Git Bash中可用的功能:
- Most core utils
- File operations
- Process management (limited)
- 大多数核心工具
- 文件操作
- 进程管理(有限)
NOT available:
Git Bash中不可用的功能:
- systemd
- Some signals (SIGHUP behavior differs)
- /proc filesystem
- Native Windows path handling issues
- systemd
- 部分信号(SIGHUP行为不同)
- /proc文件系统
- 原生Windows路径处理问题
Path handling
路径处理
Git Bash uses Unix paths: /c/Users/...
Git Bash使用Unix路径: /c/Users/...
Convert if needed:
需要时转换:
winpath=$(cygpath -w "$unixpath") # Unix → Windows
unixpath=$(cygpath -u "$winpath") # Windows → Unix
winpath=$(cygpath -w "$unixpath") # Unix → Windows
unixpath=$(cygpath -u "$winpath") # Windows → Unix
Check for Git Bash
检测Git Bash
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
# Git Bash / Cygwin code
fi
**WSL (Windows Subsystem for Linux):**
```bashif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
# Git Bash / Cygwin代码
fi
**WSL(Windows子系统Linux):**
```bashWSL is essentially Linux, but:
WSL本质上是Linux,但:
- Can access Windows filesystem at /mnt/c/
- 可通过/mnt/c/访问Windows文件系统
- Some syscalls behave differently
- 部分系统调用行为不同
- Network configuration differs
- 网络配置不同
Check for WSL
检测WSL
if grep -qi microsoft /proc/version 2>/dev/null; then
# WSL-specific code
fi
undefinedif grep -qi microsoft /proc/version 2>/dev/null; then
# WSL特有代码
fi
undefinedContainers (Docker/Kubernetes)
容器(Docker/Kubernetes)
Container-aware scripting:
bash
undefined容器感知脚本:
bash
undefinedMinimal base images may not have bash
最小化基础镜像可能没有Bash
Use #!/bin/sh or install bash explicitly
使用#!/bin/sh或显式安装Bash
Container detection
容器检测
if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then
# Running in Docker
fi
if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then
# 在Docker中运行
fi
Kubernetes detection
Kubernetes检测
if [ -n "$KUBERNETES_SERVICE_HOST" ]; then
# Running in Kubernetes
fi
if [ -n "$KUBERNETES_SERVICE_HOST" ]; then
# 在Kubernetes中运行
fi
Best practices:
最佳实践:
- Minimize dependencies
- 最小化依赖
- Use absolute paths or PATH
- 使用绝对路径或PATH
- Don't assume user/group existence
- 不要假设用户/组存在
- Handle signals properly (PID 1 issues)
- 正确处理信号(PID 1问题)
undefinedundefinedCross-Platform Template
跨平台模板
bash
#!/usr/bin/env bash
set -euo pipefailbash
#!/usr/bin/env bash
set -euo pipefailDetect platform
检测平台
detect_platform() {
case "$OSTYPE" in
linux-gnu*) echo "linux" ;;
darwin*) echo "macos" ;;
msys*|cygwin*) echo "windows" ;;
*) echo "unknown" ;;
esac
}
PLATFORM=$(detect_platform)
detect_platform() {
case "$OSTYPE" in
linux-gnu*) echo "linux" ;;
darwin*) echo "macos" ;;
msys*|cygwin*) echo "windows" ;;
*) echo "unknown" ;;
esac
}
PLATFORM=$(detect_platform)
Platform-specific paths
平台特定路径
case "$PLATFORM" in
linux)
SED=sed
;;
macos)
SED=$(command -v gsed || echo sed)
;;
windows)
# Git Bash specifics
;;
esac
---case "$PLATFORM" in
linux)
SED=sed
;;
macos)
SED=$(command -v gsed || echo sed)
;;
windows)
# Git Bash特有的设置
;;
esac
---Best Practices
最佳实践
Function Design
函数设计
bash
undefinedbash
undefinedGood function structure
良好的函数结构
function_name() {
# 1. Local variables first
local arg1="$1"
local arg2="${2:-default_value}"
local result=""
# 2. Input validation
if [[ -z "$arg1" ]]; then
echo "Error: arg1 is required" >&2
return 1
fi
# 3. Main logic
result=$(some_operation "$arg1" "$arg2")
# 4. Output/return
echo "$result"
return 0}
function_name() {
# 1. 先定义局部变量
local arg1="$1"
local arg2="${2:-default_value}"
local result=""
# 2. 输入验证
if [[ -z "$arg1" ]]; then
echo "错误: 参数arg1是必填项" >&2
return 1
fi
# 3. 主逻辑
result=$(some_operation "$arg1" "$arg2")
# 4. 输出/返回
echo "$result"
return 0}
Use functions, not scripts-in-scripts
使用函数,而非脚本嵌套脚本
Benefits: testability, reusability, namespacing
优势: 可测试性、可复用性、命名空间
undefinedundefinedVariable Naming
变量命名
bash
undefinedbash
undefinedConstants: UPPER_CASE
常量: 大写蛇形命名
readonly MAX_RETRIES=3
readonly CONFIG_FILE="/etc/app/config.conf"
readonly MAX_RETRIES=3
readonly CONFIG_FILE="/etc/app/config.conf"
Global variables: UPPER_CASE or lower_case (be consistent)
全局变量: 大写蛇形或小写蛇形(保持一致)
GLOBAL_STATE="initialized"
GLOBAL_STATE="initialized"
Local variables: lower_case
局部变量: 小写蛇形
local user_name="john"
local file_count=0
local user_name="john"
local file_count=0
Environment variables: UPPER_CASE (by convention)
环境变量: 大写蛇形(惯例)
export DATABASE_URL="postgres://..."
export DATABASE_URL="postgres://..."
Readonly when possible
尽可能使用只读
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
undefinedreadonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
undefinedError Handling
错误处理
bash
undefinedbash
undefinedMethod 1: Check exit codes explicitly
方法1: 显式检查退出码
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
return 1
fi
if ! command_that_might_fail; then
echo "错误: 命令执行失败" >&2
return 1
fi
Method 2: Use || for alternative actions
方法2: 使用||执行替代操作
command_that_might_fail || {
echo "Error: Command failed" >&2
return 1
}
command_that_might_fail || {
echo "错误: 命令执行失败" >&2
return 1
}
Method 3: Trap for cleanup
方法3: 使用陷阱进行清理
cleanup() {
local exit_code=$?
# Cleanup operations
rm -f "$TEMP_FILE"
exit "$exit_code"
}
trap cleanup EXIT
cleanup() {
local exit_code=$?
# 清理操作
rm -f "$TEMP_FILE"
exit "$exit_code"
}
trap cleanup EXIT
Method 4: Custom error handler
方法4: 自定义错误处理器
error_exit() {
local message="$1"
local code="${2:-1}"
echo "Error: $message" >&2
exit "$code"
}
error_exit() {
local message="$1"
local code="${2:-1}"
echo "错误: $message" >&2
exit "$code"
}
Usage
使用示例
[[ -f "$config_file" ]] || error_exit "Config file not found: $config_file"
undefined[[ -f "$config_file" ]] || error_exit "未找到配置文件: $config_file"
undefinedInput Validation
输入验证
bash
validate_input() {
local input="$1"
# Check if empty
if [[ -z "$input" ]]; then
echo "Error: Input cannot be empty" >&2
return 1
fi
# Check format (example: alphanumeric only)
if [[ ! "$input" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Error: Input contains invalid characters" >&2
return 1
fi
# Check length
if [[ ${#input} -gt 255 ]]; then
echo "Error: Input too long (max 255 characters)" >&2
return 1
fi
return 0
}bash
validate_input() {
local input="$1"
# 检查是否为空
if [[ -z "$input" ]]; then
echo "错误: 输入不能为空" >&2
return 1
fi
# 检查格式(示例:仅允许字母数字)
if [[ ! "$input" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "错误: 输入包含无效字符" >&2
return 1
fi
# 检查长度
if [[ ${#input} -gt 255 ]]; then
echo "错误: 输入过长(最多255个字符)" >&2
return 1
fi
return 0
}Validate before use
使用前验证
read -r user_input
if validate_input "$user_input"; then
process "$user_input"
fi
undefinedread -r user_input
if validate_input "$user_input"; then
process "$user_input"
fi
undefinedArgument Parsing
参数解析
bash
undefinedbash
undefinedSimple argument parsing
简单参数解析
usage() {
cat <<EOF
Usage: $SCRIPT_NAME [OPTIONS] <command>
Options:
-h, --help Show this help
-v, --verbose Verbose output
-f, --file FILE Input file
-o, --output DIR Output directory
Commands:
build Build the project
test Run tests
EOF
}
main() {
local verbose=false
local input_file=""
local output_dir="."
local command=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-v|--verbose)
verbose=true
shift
;;
-f|--file)
input_file="$2"
shift 2
;;
-o|--output)
output_dir="$2"
shift 2
;;
-*)
echo "Error: Unknown option: $1" >&2
usage >&2
exit 1
;;
*)
command="$1"
shift
break
;;
esac
done
# Validate required arguments
if [[ -z "$command" ]]; then
echo "Error: Command is required" >&2
usage >&2
exit 1
fi
# Execute command
case "$command" in
build) do_build ;;
test) do_test ;;
*)
echo "Error: Unknown command: $command" >&2
usage >&2
exit 1
;;
esac}
main "$@"
undefinedusage() {
cat <<EOF
用法: $SCRIPT_NAME [选项] <命令>
选项:
-h, --help 显示此帮助信息
-v, --verbose 详细输出
-f, --file 文件 输入文件
-o, --output 目录 输出目录
命令:
build 构建项目
test 运行测试
EOF
}
main() {
local verbose=false
local input_file=""
local output_dir="."
local command=""
# 解析参数
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-v|--verbose)
verbose=true
shift
;;
-f|--file)
input_file="$2"
shift 2
;;
-o|--output)
output_dir="$2"
shift 2
;;
-*)
echo "错误: 未知选项: $1" >&2
usage >&2
exit 1
;;
*)
command="$1"
shift
break
;;
esac
done
# 验证必填参数
if [[ -z "$command" ]]; then
echo "错误: 命令是必填项" >&2
usage >&2
exit 1
fi
# 执行命令
case "$command" in
build) do_build ;;
test) do_test ;;
*)
echo "错误: 未知命令: $command" >&2
usage >&2
exit 1
;;
esac}
main "$@"
undefinedLogging
日志
bash
undefinedbash
undefinedLogging levels
日志级别
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
Current log level
当前日志级别
LOG_LEVEL=${LOG_LEVEL:-$LOG_LEVEL_INFO}
log_debug() { [[ $LOG_LEVEL -le $LOG_LEVEL_DEBUG ]] && echo "[DEBUG] $" >&2; }
log_info() { [[ $LOG_LEVEL -le $LOG_LEVEL_INFO ]] && echo "[INFO] $" >&2; }
log_warn() { [[ $LOG_LEVEL -le $LOG_LEVEL_WARN ]] && echo "[WARN] $" >&2; }
log_error() { [[ $LOG_LEVEL -le $LOG_LEVEL_ERROR ]] && echo "[ERROR] $" >&2; }
LOG_LEVEL=${LOG_LEVEL:-$LOG_LEVEL_INFO}
log_debug() { [[ $LOG_LEVEL -le $LOG_LEVEL_DEBUG ]] && echo "[DEBUG] $" >&2; }
log_info() { [[ $LOG_LEVEL -le $LOG_LEVEL_INFO ]] && echo "[INFO] $" >&2; }
log_warn() { [[ $LOG_LEVEL -le $LOG_LEVEL_WARN ]] && echo "[WARN] $" >&2; }
log_error() { [[ $LOG_LEVEL -le $LOG_LEVEL_ERROR ]] && echo "[ERROR] $" >&2; }
With timestamps
带时间戳的日志
log_with_timestamp() {
local level="$1"
shift
echo "[$(date +'%Y-%m-%d %H:%M:%S')] [$level] $*" >&2
}
log_with_timestamp() {
local level="$1"
shift
echo "[$(date +'%Y-%m-%d %H:%M:%S')] [$level] $*" >&2
}
Usage
使用示例
log_info "Starting process"
log_error "Failed to connect to database"
---log_info "开始执行流程"
log_error "数据库连接失败"
---Security Best Practices
安全最佳实践
Command Injection Prevention
命令注入防护
bash
undefinedbash
undefinedNEVER use eval with user input
绝不要将用户输入与eval一起使用
✗ WRONG - DANGEROUS
✗ 错误 - 危险
eval "$user_input"
eval "$user_input"
NEVER use dynamic variable names from user input
绝不要使用来自用户输入的动态变量名
✗ WRONG - DANGEROUS
✗ 错误 - 危险
eval "var_$user_input=value"
eval "var_$user_input=value"
NEVER concatenate user input into commands
绝不要将用户输入拼接进命令
✗ WRONG - DANGEROUS
✗ 错误 - 危险
grep "$user_pattern" file.txt # If pattern contains -e flag, injection possible
grep "$user_pattern" file.txt # 如果模式包含-e标志,可能被注入
✓ CORRECT - Use arrays
✓ 正确 - 使用数组
grep_args=("$user_pattern" "file.txt")
grep "${grep_args[@]}"
grep_args=("$user_pattern" "file.txt")
grep "${grep_args[@]}"
✓ CORRECT - Use -- to separate options from arguments
✓ 正确 - 使用--分隔选项与参数
grep -- "$user_pattern" file.txt
undefinedgrep -- "$user_pattern" file.txt
undefinedPath Traversal Prevention
路径遍历防护
bash
undefinedbash
undefinedSanitize file paths
清理文件路径
sanitize_path() {
local path="$1"
# Remove .. components
path="${path//..\/}"
path="${path//\/..\//}"
# Remove leading /
path="${path#/}"
echo "$path"}
sanitize_path() {
local path="$1"
# 移除..组件
path="${path//..\/}"
path="${path//\/..\//}"
# 移除开头的/
path="${path#/}"
echo "$path"}
Validate path is within allowed directory
验证路径是否在允许的目录内
is_safe_path() {
local file_path="$1"
local base_dir="$2"
# Resolve to absolute path
local real_path
real_path=$(readlink -f "$file_path" 2>/dev/null) || return 1
local real_base
real_base=$(readlink -f "$base_dir" 2>/dev/null) || return 1
# Check if path starts with base directory
[[ "$real_path" == "$real_base"/* ]]}
is_safe_path() {
local file_path="$1"
local base_dir="$2"
# 解析为绝对路径
local real_path
real_path=$(readlink -f "$file_path" 2>/dev/null) || return 1
local real_base
real_base=$(readlink -f "$base_dir" 2>/dev/null) || return 1
# 检查路径是否以基础目录开头
[[ "$real_path" == "$real_base"/* ]]}
Usage
使用示例
if is_safe_path "$user_file" "/var/app/data"; then
process_file "$user_file"
else
echo "Error: Invalid file path" >&2
exit 1
fi
undefinedif is_safe_path "$user_file" "/var/app/data"; then
process_file "$user_file"
else
echo "错误: 文件路径无效" >&2
exit 1
fi
undefinedPrivilege Management
权限管理
bash
undefinedbash
undefinedCheck if running as root
检查是否以root身份运行
if [[ $EUID -eq 0 ]]; then
echo "Error: Do not run this script as root" >&2
exit 1
fi
if [[ $EUID -eq 0 ]]; then
echo "错误: 不要以root身份运行此脚本" >&2
exit 1
fi
Drop privileges if needed
必要时降低权限
drop_privileges() {
local user="$1"
if [[ $EUID -eq 0 ]]; then
exec sudo -u "$user" "$0" "$@"
fi}
drop_privileges() {
local user="$1"
if [[ $EUID -eq 0 ]]; then
exec sudo -u "$user" "$0" "$@"
fi}
Run specific command with elevated privileges
使用提升的权限运行特定命令
run_as_root() {
if [[ $EUID -ne 0 ]]; then
sudo "$@"
else
"$@"
fi
}
undefinedrun_as_root() {
if [[ $EUID -ne 0 ]]; then
sudo "$@"
else
"$@"
fi
}
undefinedTemporary File Handling
临时文件处理
bash
undefinedbash
undefinedCreate secure temporary files
创建安全的临时文件
readonly TEMP_DIR=$(mktemp -d)
readonly TEMP_FILE=$(mktemp)
readonly TEMP_DIR=$(mktemp -d)
readonly TEMP_FILE=$(mktemp)
Cleanup on exit
退出时清理
cleanup() {
rm -rf "$TEMP_DIR"
rm -f "$TEMP_FILE"
}
trap cleanup EXIT
cleanup() {
rm -rf "$TEMP_DIR"
rm -f "$TEMP_FILE"
}
trap cleanup EXIT
Secure temporary file (only readable by owner)
安全临时文件(仅所有者可读)
secure_temp=$(mktemp)
chmod 600 "$secure_temp"
---secure_temp=$(mktemp)
chmod 600 "$secure_temp"
---Performance Optimization
性能优化
Avoid Unnecessary Subshells
避免不必要的子Shell
bash
undefinedbash
undefined✗ SLOW - Creates subshell for each iteration
✗ 缓慢 - 每次迭代创建子Shell
while IFS= read -r line; do
count=$(echo "$count + 1" | bc)
done < file.txt
while IFS= read -r line; do
count=$(echo "$count + 1" | bc)
done < file.txt
✓ FAST - Arithmetic in bash
✓ 快速 - Bash内置算术运算
count=0
while IFS= read -r line; do
((count++))
done < file.txt
undefinedcount=0
while IFS= read -r line; do
((count++))
done < file.txt
undefinedUse Bash Built-ins
使用Bash内置命令
bash
undefinedbash
undefined✗ SLOW - External commands
✗ 缓慢 - 外部命令
dirname=$(dirname "$path")
basename=$(basename "$path")
dirname=$(dirname "$path")
basename=$(basename "$path")
✓ FAST - Parameter expansion
✓ 快速 - 参数扩展
dirname="${path%/}"
basename="${path##/}"
dirname="${path%/}"
basename="${path##/}"
✗ SLOW - grep for simple checks
✗ 缓慢 - 使用grep进行简单检查
if echo "$string" | grep -q "pattern"; then
if echo "$string" | grep -q "pattern"; then
✓ FAST - Bash regex
✓ 快速 - Bash正则表达式
if [[ "$string" =~ pattern ]]; then
if [[ "$string" =~ pattern ]]; then
✗ SLOW - awk for simple extraction
✗ 缓慢 - 使用awk进行简单提取
field=$(echo "$line" | awk '{print $3}')
field=$(echo "$line" | awk '{print $3}')
✓ FAST - Read into array
✓ 快速 - 读取到数组
read -ra fields <<< "$line"
field="${fields[2]}"
undefinedread -ra fields <<< "$line"
field="${fields[2]}"
undefinedProcess Substitution vs Pipes
进程替换 vs 管道
bash
undefinedbash
undefinedWhen you need to read multiple commands' output
当需要读取多个命令的输出时
✓ GOOD - Process substitution
✓ 推荐 - 进程替换
while IFS= read -r line1 <&3 && IFS= read -r line2 <&4; do
echo "$line1 - $line2"
done 3< <(command1) 4< <(command2)
while IFS= read -r line1 <&3 && IFS= read -r line2 <&4; do
echo "$line1 - $line2"
done 3< <(command1) 4< <(command2)
Parallel processing
并行处理
command1 &
command2 &
wait # Wait for all background jobs
undefinedcommand1 &
command2 &
wait # 等待所有后台任务完成
undefinedArray Operations
数组操作
bash
undefinedbash
undefined✓ FAST - Native array operations
✓ 快速 - 原生数组操作
files=(*.txt)
echo "Found ${#files[@]} files"
files=(*.txt)
echo "找到 ${#files[@]} 个文件"
✗ SLOW - Parsing ls output
✗ 缓慢 - 解析ls输出
count=$(ls -1 *.txt | wc -l)
count=$(ls -1 *.txt | wc -l)
✓ FAST - Array filtering
✓ 快速 - 数组过滤
filtered=()
for item in "${array[@]}"; do
[[ "$item" =~ ^[0-9]+$ ]] && filtered+=("$item")
done
filtered=()
for item in "${array[@]}"; do
[[ "$item" =~ ^[0-9]+$ ]] && filtered+=("$item")
done
✓ FAST - Array joining
✓ 快速 - 数组拼接
IFS=,
joined="${array[*]}"
IFS=$'\n\t'
---IFS=,
joined="${array[*]}"
IFS=$'\n\t'
---Testing
测试
Unit Testing with BATS
使用BATS进行单元测试
bash
undefinedbash
undefinedInstall BATS
安装BATS
cd bats-core && ./install.sh /usr/local
cd bats-core && ./install.sh /usr/local
test/script.bats
test/script.bats
#!/usr/bin/env bats
#!/usr/bin/env bats
Load script to test
加载要测试的脚本
load '../script.sh'
@test "function returns correct value" {
result=$(my_function "input")
[ "$result" = "expected" ]
}
@test "function handles empty input" {
run my_function ""
[ "$status" -eq 1 ]
[ "${lines[0]}" = "Error: Input cannot be empty" ]
}
@test "function validates input format" {
run my_function "invalid@input"
[ "$status" -eq 1 ]
}
load '../script.sh'
@test "函数返回正确值" {
result=$(my_function "input")
[ "$result" = "expected" ]
}
@test "函数处理空输入" {
run my_function ""
[ "$status" -eq 1 ]
[ "${lines[0]}" = "错误: 输入不能为空" ]
}
@test "函数验证输入格式" {
run my_function "invalid@input"
[ "$status" -eq 1 ]
}
Run tests
运行测试
bats test/script.bats
bats test/script.bats
undefinedundefinedIntegration Testing
集成测试
bash
undefinedbash
undefinedintegration_test.sh
integration_test.sh
#!/usr/bin/env bash
set -euo pipefail
#!/usr/bin/env bash
set -euo pipefail
Setup
初始化
setup() {
export TEST_DIR=$(mktemp -d)
export TEST_FILE="$TEST_DIR/test.txt"
}
setup() {
export TEST_DIR=$(mktemp -d)
export TEST_FILE="$TEST_DIR/test.txt"
}
Teardown
清理
teardown() {
rm -rf "$TEST_DIR"
}
teardown() {
rm -rf "$TEST_DIR"
}
Test case
测试用例
test_file_creation() {
./script.sh create "$TEST_FILE"
if [[ ! -f "$TEST_FILE" ]]; then
echo "FAIL: File was not created"
return 1
fi
echo "PASS: File creation works"
return 0}
test_file_creation() {
./script.sh create "$TEST_FILE"
if [[ ! -f "$TEST_FILE" ]]; then
echo "失败: 文件未创建"
return 1
fi
echo "通过: 文件创建功能正常"
return 0}
Run tests
运行测试
main() {
setup
trap teardown EXIT
test_file_creation || exit 1
echo "All tests passed"}
main
undefinedmain() {
setup
trap teardown EXIT
test_file_creation || exit 1
echo "所有测试通过"}
main
undefinedCI/CD Integration
CI/CD集成
yaml
undefinedyaml
undefined.github/workflows/test.yml
.github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install shellcheck
run: sudo apt-get install -y shellcheck
- name: Run shellcheck
run: find . -name "*.sh" -exec shellcheck {} +
- name: Install bats
run: |
git clone https://github.com/bats-core/bats-core.git
cd bats-core
sudo ./install.sh /usr/local
- name: Run tests
run: bats test/
---name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install shellcheck
run: sudo apt-get install -y shellcheck
- name: Run shellcheck
run: find . -name "*.sh" -exec shellcheck {} +
- name: Install bats
run: |
git clone https://github.com/bats-core/bats-core.git
cd bats-core
sudo ./install.sh /usr/local
- name: Run tests
run: bats test/
---Debugging Techniques
调试技巧
Debug Mode
调试模式
bash
undefinedbash
undefinedMethod 1: set -x (print commands)
方法1: set -x(打印命令)
set -x
command1
command2
set +x # Turn off
set -x
command1
command2
set +x # 关闭调试
Method 2: PS4 for better output
方法2: 设置PS4以获得更清晰的输出
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -x
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -x
Method 3: Conditional debugging
方法3: 条件调试
DEBUG=${DEBUG:-false}
debug() {
if [[ "$DEBUG" == "true" ]]; then
echo "[DEBUG] $*" >&2
fi
}
DEBUG=${DEBUG:-false}
debug() {
if [[ "$DEBUG" == "true" ]]; then
echo "[DEBUG] $*" >&2
fi
}
Usage: DEBUG=true ./script.sh
使用方式: DEBUG=true ./script.sh
undefinedundefinedTracing and Profiling
跟踪与性能分析
bash
undefinedbash
undefinedTrace function calls
跟踪函数调用
trace() {
echo "[TRACE] Function: ${FUNCNAME[1]}, Args: $*" >&2
}
my_function() {
trace "$@"
# Function logic
}
trace() {
echo "[TRACE] 函数: ${FUNCNAME[1]}, 参数: $*" >&2
}
my_function() {
trace "$@"
# 函数逻辑
}
Execution time profiling
执行时间分析
profile() {
local start=$(date +%s%N)
"$@"
local end=$(date +%s%N)
local duration=$(( (end - start) / 1000000 ))
echo "[PROFILE] Command '$*' took ${duration}ms" >&2
}
profile() {
local start=$(date +%s%N)
"$@"
local end=$(date +%s%N)
local duration=$(( (end - start) / 1000000 ))
echo "[PROFILE] 命令'$*'耗时 ${duration}ms" >&2
}
Usage
使用示例
profile slow_command arg1 arg2
undefinedprofile slow_command arg1 arg2
undefinedCommon Issues and Solutions
常见问题与解决方案
bash
undefinedbash
undefinedIssue: Script works in bash but not in sh
问题: 脚本在bash中运行正常但在sh中失败
Solution: Check for bashisms
解决方案: 检查Bash特有语法
checkbashisms script.sh
checkbashisms script.sh
Issue: Works locally but not on server
问题: 在本地运行正常但在服务器上失败
Solution: Check PATH and environment
解决方案: 检查PATH和环境变量
env
echo "$PATH"
env
echo "$PATH"
Issue: Whitespace in filenames breaking script
问题: 文件名中的空格导致脚本出错
Solution: Always quote variables
解决方案: 始终引用变量
for file in *.txt; do
process "$file" # Not: process $file
done
for file in *.txt; do
process "$file" # 不要写成: process $file
done
Issue: Script behaves differently in cron
问题: 脚本在cron中的行为不同
Solution: Set PATH explicitly
解决方案: 显式设置PATH
PATH=/usr/local/bin:/usr/bin:/bin
export PATH
---PATH=/usr/local/bin:/usr/bin:/bin
export PATH
---Advanced Patterns
高级模式
Configuration File Parsing
配置文件解析
bash
undefinedbash
undefinedSimple key=value config
简单的key=value配置
load_config() {
local config_file="$1"
if [[ ! -f "$config_file" ]]; then
echo "Error: Config file not found: $config_file" >&2
return 1
fi
# Source config (dangerous if not trusted)
# shellcheck source=/dev/null
source "$config_file"}
load_config() {
local config_file="$1"
if [[ ! -f "$config_file" ]]; then
echo "错误: 未找到配置文件: $config_file" >&2
return 1
fi
# 加载配置(如果配置不可信则危险)
# shellcheck source=/dev/null
source "$config_file"}
Safe config parsing (no code execution)
安全的配置解析(无代码执行)
read_config() {
local config_file="$1"
while IFS='=' read -r key value; do
# Skip comments and empty lines
[[ "$key" =~ ^[[:space:]]*# ]] && continue
[[ -z "$key" ]] && continue
# Trim whitespace
key=$(echo "$key" | tr -d ' ')
value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# Export variable
declare -g "$key=$value"
done < "$config_file"}
undefinedread_config() {
local config_file="$1"
while IFS='=' read -r key value; do
# 跳过注释和空行
[[ "$key" =~ ^[[:space:]]*# ]] && continue
[[ -z "$key" ]] && continue
# 去除空格
key=$(echo "$key" | tr -d ' ')
value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# 导出变量
declare -g "$key=$value"
done < "$config_file"}
undefinedParallel Processing
并行处理
bash
undefinedbash
undefinedSimple background jobs
简单的后台任务
process_files_parallel() {
local max_jobs=4
local job_count=0
for file in *.txt; do
# Start background job
process_file "$file" &
# Limit concurrent jobs
((job_count++))
if [[ $job_count -ge $max_jobs ]]; then
wait -n # Wait for any job to finish
((job_count--))
fi
done
# Wait for remaining jobs
wait}
process_files_parallel() {
local max_jobs=4
local job_count=0
for file in *.txt; do
# 启动后台任务
process_file "$file" &
# 限制并发任务数
((job_count++))
if [[ $job_count -ge $max_jobs ]]; then
wait -n # 等待任意任务完成
((job_count--))
fi
done
# 等待剩余任务完成
wait}
GNU Parallel (if available)
使用GNU Parallel(如果可用)
parallel_with_gnu() {
parallel -j 4 process_file ::: *.txt
}
undefinedparallel_with_gnu() {
parallel -j 4 process_file ::: *.txt
}
undefinedSignal Handling
信号处理
bash
undefinedbash
undefinedGraceful shutdown
优雅关闭
shutdown_requested=false
handle_sigterm() {
echo "Received SIGTERM, shutting down gracefully..." >&2
shutdown_requested=true
}
trap handle_sigterm SIGTERM SIGINT
main_loop() {
while [[ "$shutdown_requested" == "false" ]]; do
# Do work
sleep 1
done
echo "Shutdown complete" >&2}
main_loop
undefinedshutdown_requested=false
handle_sigterm() {
echo "收到SIGTERM信号,正在优雅关闭..." >&2
shutdown_requested=true
}
trap handle_sigterm SIGTERM SIGINT
main_loop() {
while [[ "$shutdown_requested" == "false" ]]; do
# 执行任务
sleep 1
done
echo "关闭完成" >&2}
main_loop
undefinedRetries with Exponential Backoff
指数退避重试
bash
retry_with_backoff() {
local max_attempts=5
local timeout=1
local attempt=1
local exitCode=0
while [[ $attempt -le $max_attempts ]]; do
if "$@"; then
return 0
else
exitCode=$?
fi
echo "Attempt $attempt failed! Retrying in $timeout seconds..." >&2
sleep "$timeout"
attempt=$((attempt + 1))
timeout=$((timeout * 2))
done
echo "Command failed after $max_attempts attempts!" >&2
return "$exitCode"
}bash
retry_with_backoff() {
local max_attempts=5
local timeout=1
local attempt=1
local exitCode=0
while [[ $attempt -le $max_attempts ]]; do
if "$@"; then
return 0
else
exitCode=$?
fi
echo "第$attempt次尝试失败!$timeout秒后重试..." >&2
sleep "$timeout"
attempt=$((attempt + 1))
timeout=$((timeout * 2))
done
echo "命令在$max_attempts次尝试后失败!" >&2
return "$exitCode"
}Usage
使用示例
retry_with_backoff curl -f https://api.example.com/health
---retry_with_backoff curl -f https://api.example.com/health
---Resources for Additional Information
更多信息资源
Official Documentation
官方文档
-
Bash Reference Manual
- URL: https://www.gnu.org/software/bash/manual/
- The authoritative source for bash features and behavior
-
POSIX Shell Command Language
- URL: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
- For writing portable scripts
-
Bash参考手册
- URL: https://www.gnu.org/software/bash/manual/
- Bash特性与行为的权威来源
-
POSIX Shell命令语言
Style Guides
风格指南
-
Google Shell Style Guide
- URL: https://google.github.io/styleguide/shellguide.html
- Industry-standard practices from Google
-
Defensive Bash Programming
- URL: https://kfirlavi.herokuapp.com/blog/2012/11/14/defensive-bash-programming
- Best practices for robust scripts
-
Google Shell风格指南
- URL: https://google.github.io/styleguide/shellguide.html
- Google制定的行业标准实践
-
防御性Bash编程
Tools
工具
-
ShellCheck
- URL: https://www.shellcheck.net/
- GitHub: https://github.com/koalaman/shellcheck
- Static analysis tool for shell scripts
-
BATS (Bash Automated Testing System)
- GitHub: https://github.com/bats-core/bats-core
- Unit testing framework for bash
-
shfmt
- GitHub: https://github.com/mvdan/sh
- Shell script formatter
-
ShellCheck
- URL: https://www.shellcheck.net/
- GitHub: https://github.com/koalaman/shellcheck
- Shell脚本静态分析工具
-
BATS(Bash自动化测试系统)
- GitHub: https://github.com/bats-core/bats-core
- Bash单元测试框架
-
shfmt
- GitHub: https://github.com/mvdan/sh
- Shell脚本格式化工具
Learning Resources
学习资源
-
Bash Academy
- URL: https://www.bash.academy/
- Comprehensive bash learning resource
-
Bash Guide for Beginners
- URL: https://tldp.org/LDP/Bash-Beginners-Guide/html/
- From The Linux Documentation Project
-
Advanced Bash-Scripting Guide
- URL: https://tldp.org/LDP/abs/html/
- In-depth coverage of advanced topics
-
Bash Pitfalls
- URL: https://mywiki.wooledge.org/BashPitfalls
- Common mistakes and how to avoid them
-
explainshell.com
- URL: https://explainshell.com/
- Interactive tool to explain shell commands
-
Bash学院
- URL: https://www.bash.academy/
- 全面的Bash学习资源
-
Bash初学者指南
- URL: https://tldp.org/LDP/Bash-Beginners-Guide/html/
- 来自Linux文档项目
-
高级Bash脚本指南
- URL: https://tldp.org/LDP/abs/html/
- 深入覆盖高级主题
-
Bash陷阱
- URL: https://mywiki.wooledge.org/BashPitfalls
- 常见错误及避免方法
-
explainshell.com
- URL: https://explainshell.com/
- 解释Shell命令的交互式工具
Platform-Specific Resources
平台特定资源
-
GNU Coreutils Manual
- URL: https://www.gnu.org/software/coreutils/manual/
- For Linux-specific commands
-
FreeBSD Manual Pages
- URL: https://www.freebsd.org/cgi/man.cgi
- For macOS (BSD-based) differences
-
Git for Windows
- URL: https://gitforwindows.org/
- Git Bash documentation and issues
-
WSL Documentation
- URL: https://docs.microsoft.com/en-us/windows/wsl/
- Windows Subsystem for Linux specifics
-
GNU Coreutils手册
- URL: https://www.gnu.org/software/coreutils/manual/
- Linux特定命令参考
-
FreeBSD手册页
- URL: https://www.freebsd.org/cgi/man.cgi
- macOS(基于BSD)差异参考
-
Git for Windows
- URL: https://gitforwindows.org/
- Git Bash文档与问题解决
-
WSL文档
- URL: https://docs.microsoft.com/en-us/windows/wsl/
- Windows子系统Linux细节
Community Resources
社区资源
-
Stack Overflow - Bash Tag
- URL: https://stackoverflow.com/questions/tagged/bash
- Community Q&A
-
Unix & Linux Stack Exchange
- URL: https://unix.stackexchange.com/
- Shell scripting expertise
-
Reddit - r/bash
- URL: https://www.reddit.com/r/bash/
- Community discussions
-
Stack Overflow - Bash标签
-
Unix & Linux Stack Exchange
- URL: https://unix.stackexchange.com/
- Shell脚本专业知识
-
Reddit - r/bash
- URL: https://www.reddit.com/r/bash/
- 社区讨论
Quick Reference
快速参考
-
Bash Cheat Sheet
- URL: https://devhints.io/bash
- Quick syntax reference
-
ShellCheck Wiki
- URL: https://www.shellcheck.net/wiki/
- Explanations of ShellCheck warnings
-
Bash速查表
- URL: https://devhints.io/bash
- 快速语法参考
-
ShellCheck维基
- URL: https://www.shellcheck.net/wiki/
- ShellCheck警告解释
Reference Files
参考文件
For deeper coverage of specific topics, see the reference files:
- references/platform_specifics.md - Detailed platform differences and workarounds
- references/best_practices.md - Comprehensive industry standards and guidelines
- references/patterns_antipatterns.md - Common patterns and pitfalls with solutions
如需深入了解特定主题,请参阅参考文件:
- references/platform_specifics.md - 详细的平台差异与解决方案
- references/best_practices.md - 全面的行业标准与指南
- references/patterns_antipatterns.md - 常见模式与陷阱及解决方案
When to Use This Skill
何时使用本技能
Always activate for:
- Writing new bash scripts
- Reviewing/refactoring existing scripts
- Debugging shell script issues
- Cross-platform shell scripting
- DevOps automation tasks
- CI/CD pipeline scripts
- System administration automation
Key indicators:
- User mentions bash, shell, or script
- Task involves automation
- Platform compatibility is a concern
- Security or robustness is important
- Performance optimization needed
始终激活本技能的场景:
- 编写新的Bash脚本
- 审核/重构现有脚本
- 调试Shell脚本问题
- 跨平台Shell脚本开发
- DevOps自动化任务
- CI/CD流水线脚本
- 系统管理自动化
关键指标:
- 用户提及bash、shell或script
- 任务涉及自动化
- 平台兼容性是关注点
- 安全性或健壮性很重要
- 需要性能优化
Success Criteria
成功标准
A bash script using this skill should:
- ✓ Pass ShellCheck with no warnings
- ✓ Include proper error handling (set -euo pipefail)
- ✓ Quote all variable expansions
- ✓ Include usage/help text
- ✓ Use functions for reusable logic
- ✓ Include appropriate comments
- ✓ Handle edge cases (empty input, missing files, etc.)
- ✓ Work across target platforms
- ✓ Follow consistent style (Google Shell Style Guide)
- ✓ Include cleanup (trap EXIT)
Quality checklist:
bash
undefined使用本技能编写的Bash脚本应满足:
- ✓ 通过ShellCheck检查且无警告
- ✓ 包含适当的错误处理(set -euo pipefail)
- ✓ 所有变量扩展都被引用
- ✓ 包含使用说明/帮助文本
- ✓ 使用函数实现可复用逻辑
- ✓ 包含适当的注释
- ✓ 处理边缘情况(空输入、缺失文件等)
- ✓ 在目标平台上正常运行
- ✓ 遵循一致的风格(Google Shell风格指南)
- ✓ 包含清理操作(trap EXIT)
质量检查清单:
bash
undefinedRun before deployment
部署前运行
shellcheck script.sh # No errors or warnings
bash -n script.sh # Syntax check
bats test/script.bats # Unit tests pass
./script.sh --help # Usage text displays
DEBUG=true ./script.sh # Debug mode works
---shellcheck script.sh # 无错误或警告
bash -n script.sh # 语法检查
bats test/script.bats # 单元测试通过
./script.sh --help # 显示使用说明
DEBUG=true ./script.sh # 调试模式正常工作
---Troubleshooting
故障排除
Script fails on different platform
脚本在不同平台上失败
- Check for bashisms:
checkbashisms script.sh - Verify commands exist:
command -v tool_name - Test command flags: (GNU) vs
sed --version(BSD)sed
- 检查Bash特有语法:
checkbashisms script.sh - 验证命令是否存在:
command -v tool_name - 测试命令标志:(GNU) vs
sed --version(BSD)sed
ShellCheck warnings
ShellCheck警告
- Read the explanation:
shellcheck -W SC2086 - Fix the issue (don't just disable)
- Only disable with justification:
# shellcheck disable=SC2086 reason: intentional word splitting
- 阅读解释:
shellcheck -W SC2086 - 修复问题(不要仅禁用警告)
- 仅在有合理理由时禁用:
# shellcheck disable=SC2086 reason: intentional word splitting
Script works interactively but fails in cron
脚本在交互式环境中正常但在cron中失败
- Set PATH explicitly
- Use absolute paths
- Redirect output for debugging:
./script.sh >> /tmp/cron.log 2>&1
- 显式设置PATH
- 使用绝对路径
- 重定向输出以调试:
./script.sh >> /tmp/cron.log 2>&1
Performance issues
性能问题
- Profile with
time command - Enable tracing:
set -x - Avoid unnecessary subshells and external commands
- Use bash built-ins where possible
This skill provides comprehensive bash scripting knowledge. Combined with the reference files, you have access to industry-standard practices and platform-specific guidance for any bash scripting task.
- 使用分析性能
time command - 启用跟踪:
set -x - 避免不必要的子Shell和外部命令
- 尽可能使用Bash内置命令
本技能提供全面的Bash脚本知识。结合参考文件,您可获取行业标准实践和平台特定指南,应对任何Bash脚本任务。