Shell Script Safety Standards
Intermediate
Write safe shell scripts — set -euo pipefail, proper quoting, shellcheck compliance, error handling, and portable POSIX patterns for reliable automation scripts.
File Patterns
**/*.sh**/*.bash**/bin/**
This rule applies to files matching the patterns above.
Rule Content
rule-content.md
# Shell Script Safety Standards
## Rule
All shell scripts MUST start with set -euo pipefail, use proper quoting, and pass shellcheck validation.
## Format
```bash
#!/usr/bin/env bash
set -euo pipefail
```
## Requirements
### 1. Always Set Strict Mode
```bash
#!/usr/bin/env bash
set -euo pipefail
# set -e: Exit immediately if any command fails
# set -u: Error on undefined variables
# set -o pipefail: Pipe fails if any command in pipe fails
```
### 2. Always Quote Variables
```bash
# BAD: Unquoted variables — word splitting and globbing
rm -rf $DIR/$FILE # If DIR is empty, this becomes rm -rf /
echo $USER_INPUT # Globbing can expand wildcards
# GOOD: Double-quoted variables
rm -rf "${DIR:?}/${FILE:?}" # :? errors if empty
echo "${USER_INPUT}"
```
### 3. Use Shellcheck
```bash
# Install and run shellcheck on all scripts
shellcheck myscript.sh
# In CI:
# shellcheck **/*.sh
```
### 4. Proper Error Handling
```bash
#!/usr/bin/env bash
set -euo pipefail
cleanup() {
echo "Cleaning up temporary files..."
rm -rf "${TMPDIR:-}"
}
trap cleanup EXIT ERR
TMPDIR=$(mktemp -d)
echo "Working in ${TMPDIR}"
```
### 5. Use Functions for Organization
```bash
#!/usr/bin/env bash
set -euo pipefail
log_info() { echo "[INFO] $*"; }
log_error() { echo "[ERROR] $*" >&2; }
die() { log_error "$*"; exit 1; }
main() {
local env="${1:-production}"
log_info "Deploying to ${env}"
[[ -f "config/${env}.env" ]] || die "Config not found for ${env}"
deploy "${env}"
log_info "Deploy complete"
}
deploy() {
local env="$1"
# deployment logic
}
main "$@"
```
## Examples
### Good
```bash
#!/usr/bin/env bash
set -euo pipefail
readonly BACKUP_DIR="/opt/backups"
readonly MAX_BACKUPS=7
main() {
local db_name="${1:?Usage: $0 <database_name>}"
local timestamp
timestamp=$(date +%Y%m%d_%H%M%S)
local backup_file="${BACKUP_DIR}/${db_name}_${timestamp}.sql.gz"
mkdir -p "${BACKUP_DIR}"
pg_dump "${db_name}" | gzip > "${backup_file}"
# Rotate old backups
find "${BACKUP_DIR}" -name "${db_name}_*.sql.gz" -mtime "+${MAX_BACKUPS}" -delete
echo "Backup created: ${backup_file}"
}
main "$@"
```
### Bad
```bash
#!/bin/bash
# No strict mode, no quoting, no error handling
cd $BACKUP_DIR
pg_dump $1 > backup.sql
rm old_backup.sql
```
## Enforcement
Add shellcheck to CI pipeline. Require all scripts to pass shellcheck before merge.FAQ
Discussion
Loading comments...