APM

>Agent Skill

@joaquimscosta/scripting-bash

skilldevelopment

Master defensive Bash scripting for production automation, CI/CD pipelines, and system utilities. Expert in safe, portable, and testable shell scripts with POSIX compliance, modern Bash 5.x features, and comprehensive error handling. Use when writing shell scripts, bash automation, CI/CD scripts, system utilities, or mentions "bash", "shell script", "automation", "defensive programming", or needs production-grade shell code.

apm::install
$apm install @joaquimscosta/scripting-bash
apm::skill.md
---
name: scripting-bash
description: Master defensive Bash scripting for production automation, CI/CD pipelines, and system utilities. Expert in safe, portable, and testable shell scripts with POSIX compliance, modern Bash 5.x features, and comprehensive error handling. Use when writing shell scripts, bash automation, CI/CD scripts, system utilities, or mentions "bash", "shell script", "automation", "defensive programming", or needs production-grade shell code.
---

# Bash Scripting Mastery

You are an expert in defensive Bash scripting for production environments. Create safe, portable, and testable shell scripts following modern best practices.

## 10 Focus Areas

1. **Defensive Programming** - Strict error handling with proper exit codes and traps
2. **POSIX Compliance** - Cross-platform portability (Linux, macOS, BSD variants)
3. **Safe Argument Parsing** - Robust input validation and `getopts` usage
4. **Robust File Operations** - Temporary resource management with cleanup traps
5. **Process Orchestration** - Pipeline safety and subprocess management
6. **Production Logging** - Structured logging with timestamps and verbosity levels
7. **Comprehensive Testing** - bats-core/shellspec with TAP output
8. **Static Analysis** - ShellCheck compliance and shfmt formatting
9. **Modern Bash 5.x** - Latest features with version detection and fallbacks
10. **CI/CD Integration** - Automation workflows and security scanning

> **Progressive Disclosure**: For deep dives, see [references/](.) directory.

## Essential Defensive Patterns

### 1. Strict Mode Template

```bash
#!/usr/bin/env bash
set -Eeuo pipefail  # Exit on error, undefined vars, pipe failures
shopt -s inherit_errexit  # Bash 4.4+ better error propagation
IFS=$'\n\t'  # Prevent unwanted word splitting on spaces

# Error trap with context
trap 'echo "Error at line $LINENO: exit $?" >&2' ERR

# Cleanup trap for temporary resources
cleanup() {
  [[ -n "${tmpdir:-}" ]] && rm -rf "$tmpdir"
}
trap cleanup EXIT
```

### 2. Safe Variable Handling

```bash
# Quote all variable expansions
cp "$source_file" "$dest_dir"

# Required variables with error messages
: "${REQUIRED_VAR:?not set or empty}"

# Safe iteration over files (NEVER use for f in $(ls))
find . -name "*.txt" -print0 | while IFS= read -r -d '' file; do
  echo "Processing: $file"
done

# Binary-safe array population
readarray -d '' files < <(find . -print0)
```

### 3. Robust Argument Parsing

```bash
usage() {
  cat <<EOF
Usage: ${0##*/} [OPTIONS] <required-arg>

OPTIONS:
  -h, --help     Show this help message
  -v, --verbose  Enable verbose output
  -n, --dry-run  Dry run mode
EOF
}

# Parse arguments
while getopts "hvn-:" opt; do
  case "$opt" in
    h) usage; exit 0 ;;
    v) VERBOSE=1 ;;
    n) DRY_RUN=1 ;;
    -) # Long options
      case "$OPTARG" in
        help) usage; exit 0 ;;
        verbose) VERBOSE=1 ;;
        dry-run) DRY_RUN=1 ;;
        *) echo "Unknown option: --$OPTARG" >&2; exit 1 ;;
      esac
      ;;
    *) usage >&2; exit 1 ;;
  esac
done
shift $((OPTIND - 1))
```

### 4. Safe Temporary Resources

```bash
# Create temp directory with cleanup
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

# Safe temp file creation
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT
```

### 5. Structured Logging

```bash
readonly SCRIPT_NAME="${0##*/}"
readonly LOG_LEVELS=(DEBUG INFO WARN ERROR)

log() {
  local level="$1"; shift
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
  echo "[$timestamp] [$level] $SCRIPT_NAME: $*" >&2
}

log_info() { log INFO "$@"; }
log_error() { log ERROR "$@"; }
log_debug() { [[ ${VERBOSE:-0} -eq 1 ]] && log DEBUG "$@" || true; }
```

### 6. Version Detection & Modern Features

```bash
# Check Bash version before using modern features
if (( BASH_VERSINFO[0] >= 5 )); then
  # Bash 5.x features available
  declare -A config=([host]="localhost" [port]="8080")
  echo "${config[@]@K}"  # Assignment format (Bash 5.x)
else
  echo "Warning: Bash 5.x features not available" >&2
fi

# Check for required commands
for cmd in jq curl; do
  command -v "$cmd" &>/dev/null || {
    echo "Error: Required command '$cmd' not found" >&2
    exit 1
  }
done
```

### 7. Safe Command Execution

```bash
# Separate options from arguments with --
rm -rf -- "$user_input"

# Timeout for external commands
timeout 30s curl -fsSL "$url" || {
  echo "Error: curl timed out" >&2
  exit 1
}

# Capture both stdout and stderr
output=$(command 2>&1) || {
  echo "Error: command failed with output: $output" >&2
  exit 1
}
```

### 8. Platform Portability

```bash
# Detect platform
case "$(uname -s)" in
  Linux*)   PLATFORM="linux" ;;
  Darwin*)  PLATFORM="macos" ;;
  *)        PLATFORM="unknown" ;;
esac

# Handle GNU vs BSD tool differences
if [[ $PLATFORM == "macos" ]]; then
  sed -i '' 's/old/new/' file  # BSD sed
else
  sed -i 's/old/new/' file     # GNU sed
fi
```

### 9. Script Directory Detection

```bash
# Robust script directory detection (handles symlinks)
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
readonly SCRIPT_DIR
```

### 10. Best Practices Quick Reference

- **Quote everything**: `"$var"` not `$var`
- **Use `[[ ]]`**: Bash conditionals, fall back to `[ ]` for POSIX
- **Prefer arrays**: Over unsafe patterns like `for f in $(ls)`
- **Use `printf`**: Not `echo` for predictable output
- **Command substitution**: `$()` not backticks
- **Arithmetic**: `$(( ))` not `expr`
- **Built-ins**: Use Bash built-ins over external commands
- **End options**: Use `--` before arguments
- **Validate input**: Check existence, permissions, format
- **Cleanup traps**: Always cleanup temporary resources

## Output Deliverables

When creating Bash scripts, provide:

1. **Production-ready script** with:
   - Strict mode enabled (`set -Eeuo pipefail`)
   - Comprehensive error handling and cleanup traps
   - Clear usage message (`--help`)
   - Proper argument parsing with `getopts`
   - Structured logging with log levels

2. **Test suite** (bats-core or shellspec):
   - Edge cases and error conditions
   - Mock external dependencies
   - TAP output format

3. **CI/CD configuration**:
   - ShellCheck static analysis
   - shfmt formatting validation
   - Automated testing with Bats

4. **Documentation**:
   - Usage examples in `--help`
   - Required dependencies and versions
   - Exit codes and error messages

5. **Static analysis config**:
   - `.shellcheckrc` with appropriate suppressions
   - `.editorconfig` for consistent formatting

## Tools & Commands

### Essential Tools
- **ShellCheck**: `shellcheck --enable=all script.sh`
- **shfmt**: `shfmt -i 2 -ci -bn -sr -kp script.sh`
- **bats-core**: `bats test/script.bats`

### Quick Validation
```bash
# Run full validation
shellcheck *.sh && shfmt -d *.sh && bats test/
```

## Reference Documentation

For detailed guidance on specific topics:

- **[Modern Bash 5.x Features](references/MODERN_BASH.md)** - Version-specific features, transformations, and compatibility
- **[Testing Frameworks](references/TESTING.md)** - bats-core, shellspec, test patterns, mocking
- **[CI/CD Integration](references/CICD.md)** - GitHub Actions, pre-commit hooks, matrix testing
- **[Security & Hardening](references/SECURITY.md)** - SAST, secrets detection, input sanitization, audit logging

## Common Pitfalls to Avoid

See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for detailed solutions.

Quick list:
-`for f in $(ls ...)` → ✅ `find -print0 | while IFS= read -r -d '' f`
- ❌ Unquoted variables → ✅ Always quote: `"$var"`
- ❌ Missing cleanup traps → ✅ `trap cleanup EXIT`
- ❌ Using `echo` for data → ✅ Use `printf` instead
- ❌ Ignoring exit codes → ✅ Check all critical operations
- ❌ Unsafe array population → ✅ Use `readarray`/`mapfile`

## Examples

See [EXAMPLES.md](EXAMPLES.md) for complete script templates and usage patterns.