bash-master

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bash 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

**平台兼容性快速检查:**
```bash

Linux/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
    set -euo pipefail
    , trap handlers, exit codes
  • 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 bash

Fail 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
undefined

POSIX-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
undefined
bash
undefined

ALWAYS 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
undefined
flags="-v -x -z" command $flags # 有意的单词拆分
undefined

4. Use ShellCheck

4. 使用ShellCheck

ALWAYS run ShellCheck before deployment:
bash
undefined
部署前必须运行ShellCheck:
bash
undefined

Install

安装

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
references/windows-git-bash-paths.md
for comprehensive documentation.
Quick Reference:
bash
undefined
必备知识: Git Bash/MINGW会自动将Unix风格路径转换为Windows路径。这是Windows系统上跨平台脚本错误的最常见来源。
完整指南: 参阅
references/windows-git-bash-paths.md
获取全面文档。
快速参考:
bash
undefined

Automatic 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:**

```bash
case "${MSYSTEM:-}" in MINGW64|MINGW32|MSYS) echo "MSYS2/Git Bash环境: $MSYSTEM" ;; esac

**常见问题:**

```bash

Problem: 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
undefined
cd "C:\Program Files\Git" # 或者: cd /c/Program\ Files/Git
undefined

Linux

Linux

Primary target for most bash scripts:
bash
undefined
大多数Bash脚本的主要目标平台:
bash
undefined

Linux-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
undefined
if [[ "$OSTYPE" == "linux-gnu"* ]]; then # Linux特有代码 fi
undefined

macOS

macOS

BSD-based utilities (different from GNU):
bash
undefined
基于BSD的工具(与GNU不同):
bash
undefined

macOS 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
undefined
if [[ "$OSTYPE" == "darwin"* ]]; then # macOS特有代码 fi
undefined

Windows (Git Bash / WSL)

Windows (Git Bash / WSL)

Git Bash limitations:
bash
undefined
Git Bash限制:
bash
undefined

Available 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):**
```bash
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then # Git Bash / Cygwin代码 fi

**WSL(Windows子系统Linux):**
```bash

WSL 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
undefined
if grep -qi microsoft /proc/version 2>/dev/null; then # WSL特有代码 fi
undefined

Containers (Docker/Kubernetes)

容器(Docker/Kubernetes)

Container-aware scripting:
bash
undefined
容器感知脚本:
bash
undefined

Minimal 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问题)

undefined
undefined

Cross-Platform Template

跨平台模板

bash
#!/usr/bin/env bash
set -euo pipefail
bash
#!/usr/bin/env bash
set -euo pipefail

Detect 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
undefined
bash
undefined

Good 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

优势: 可测试性、可复用性、命名空间

undefined
undefined

Variable Naming

变量命名

bash
undefined
bash
undefined

Constants: 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)"
undefined
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
undefined

Error Handling

错误处理

bash
undefined
bash
undefined

Method 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"
undefined

Input 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
undefined
read -r user_input if validate_input "$user_input"; then process "$user_input" fi
undefined

Argument Parsing

参数解析

bash
undefined
bash
undefined

Simple 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 "$@"
undefined
usage() { 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 "$@"
undefined

Logging

日志

bash
undefined
bash
undefined

Logging 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
undefined
bash
undefined

NEVER 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
undefined
grep -- "$user_pattern" file.txt
undefined

Path Traversal Prevention

路径遍历防护

bash
undefined
bash
undefined

Sanitize 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
undefined
if is_safe_path "$user_file" "/var/app/data"; then process_file "$user_file" else echo "错误: 文件路径无效" >&2 exit 1 fi
undefined

Privilege Management

权限管理

bash
undefined
bash
undefined

Check 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 }
undefined
run_as_root() { if [[ $EUID -ne 0 ]]; then sudo "$@" else "$@" fi }
undefined

Temporary File Handling

临时文件处理

bash
undefined
bash
undefined

Create 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
undefined
bash
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
undefined
count=0 while IFS= read -r line; do ((count++)) done < file.txt
undefined

Use Bash Built-ins

使用Bash内置命令

bash
undefined
bash
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]}"
undefined
read -ra fields <<< "$line" field="${fields[2]}"
undefined

Process Substitution vs Pipes

进程替换 vs 管道

bash
undefined
bash
undefined

When 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
undefined
command1 & command2 & wait # 等待所有后台任务完成
undefined

Array Operations

数组操作

bash
undefined
bash
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
undefined
bash
undefined

Install 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

undefined
undefined

Integration Testing

集成测试

bash
undefined
bash
undefined

integration_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
undefined
main() { setup trap teardown EXIT
test_file_creation || exit 1

echo "所有测试通过"
}
main
undefined

CI/CD Integration

CI/CD集成

yaml
undefined
yaml
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
undefined
bash
undefined

Method 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

undefined
undefined

Tracing and Profiling

跟踪与性能分析

bash
undefined
bash
undefined

Trace 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
undefined
profile slow_command arg1 arg2
undefined

Common Issues and Solutions

常见问题与解决方案

bash
undefined
bash
undefined

Issue: 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
undefined
bash
undefined

Simple 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"
}
undefined
read_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"
}
undefined

Parallel Processing

并行处理

bash
undefined
bash
undefined

Simple 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 }
undefined
parallel_with_gnu() { parallel -j 4 process_file ::: *.txt }
undefined

Signal Handling

信号处理

bash
undefined
bash
undefined

Graceful 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
undefined
shutdown_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
undefined

Retries 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

官方文档

  1. Bash Reference Manual
  2. POSIX Shell Command Language
  1. Bash参考手册
  2. POSIX Shell命令语言

Style Guides

风格指南

  1. Google Shell Style Guide
  2. Defensive Bash Programming
  1. Google Shell风格指南
  2. 防御性Bash编程

Tools

工具

  1. ShellCheck
  2. BATS (Bash Automated Testing System)
  3. shfmt
  1. ShellCheck
  2. BATS(Bash自动化测试系统)
  3. shfmt

Learning Resources

学习资源

  1. Bash Academy
  2. Bash Guide for Beginners
  3. Advanced Bash-Scripting Guide
  4. Bash Pitfalls
  5. explainshell.com
  1. Bash学院
  2. Bash初学者指南
  3. 高级Bash脚本指南
  4. Bash陷阱
  5. explainshell.com

Platform-Specific Resources

平台特定资源

  1. GNU Coreutils Manual
  2. FreeBSD Manual Pages
  3. Git for Windows
  4. WSL Documentation
  1. GNU Coreutils手册
  2. FreeBSD手册页
  3. Git for Windows
  4. WSL文档

Community Resources

社区资源

  1. Stack Overflow - Bash Tag
  2. Unix & Linux Stack Exchange
  3. Reddit - r/bash
  1. Stack Overflow - Bash标签
  2. Unix & Linux Stack Exchange
  3. Reddit - r/bash

Quick Reference

快速参考

  1. Bash Cheat Sheet
  2. ShellCheck Wiki

  1. Bash速查表
  2. 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:
  1. ✓ Pass ShellCheck with no warnings
  2. ✓ Include proper error handling (set -euo pipefail)
  3. ✓ Quote all variable expansions
  4. ✓ Include usage/help text
  5. ✓ Use functions for reusable logic
  6. ✓ Include appropriate comments
  7. ✓ Handle edge cases (empty input, missing files, etc.)
  8. ✓ Work across target platforms
  9. ✓ Follow consistent style (Google Shell Style Guide)
  10. ✓ Include cleanup (trap EXIT)
Quality checklist:
bash
undefined
使用本技能编写的Bash脚本应满足:
  1. ✓ 通过ShellCheck检查且无警告
  2. ✓ 包含适当的错误处理(set -euo pipefail)
  3. ✓ 所有变量扩展都被引用
  4. ✓ 包含使用说明/帮助文本
  5. ✓ 使用函数实现可复用逻辑
  6. ✓ 包含适当的注释
  7. ✓ 处理边缘情况(空输入、缺失文件等)
  8. ✓ 在目标平台上正常运行
  9. ✓ 遵循一致的风格(Google Shell风格指南)
  10. ✓ 包含清理操作(trap EXIT)
质量检查清单:
bash
undefined

Run 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

脚本在不同平台上失败

  1. Check for bashisms:
    checkbashisms script.sh
  2. Verify commands exist:
    command -v tool_name
  3. Test command flags:
    sed --version
    (GNU) vs
    sed
    (BSD)
  1. 检查Bash特有语法:
    checkbashisms script.sh
  2. 验证命令是否存在:
    command -v tool_name
  3. 测试命令标志:
    sed --version
    (GNU) vs
    sed
    (BSD)

ShellCheck warnings

ShellCheck警告

  1. Read the explanation:
    shellcheck -W SC2086
  2. Fix the issue (don't just disable)
  3. Only disable with justification:
    # shellcheck disable=SC2086 reason: intentional word splitting
  1. 阅读解释:
    shellcheck -W SC2086
  2. 修复问题(不要仅禁用警告)
  3. 仅在有合理理由时禁用:
    # shellcheck disable=SC2086 reason: intentional word splitting

Script works interactively but fails in cron

脚本在交互式环境中正常但在cron中失败

  1. Set PATH explicitly
  2. Use absolute paths
  3. Redirect output for debugging:
    ./script.sh >> /tmp/cron.log 2>&1
  1. 显式设置PATH
  2. 使用绝对路径
  3. 重定向输出以调试:
    ./script.sh >> /tmp/cron.log 2>&1

Performance issues

性能问题

  1. Profile with
    time command
  2. Enable tracing:
    set -x
  3. Avoid unnecessary subshells and external commands
  4. 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.
  1. 使用
    time command
    分析性能
  2. 启用跟踪:
    set -x
  3. 避免不必要的子Shell和外部命令
  4. 尽可能使用Bash内置命令

本技能提供全面的Bash脚本知识。结合参考文件,您可获取行业标准实践和平台特定指南,应对任何Bash脚本任务。