Bash Scripting Sunday #2: Writing a Safe and Robust Bash Script⌗

In today’s post, I’d like to give some insight into writing safer scripts using Bash’s built-in options.

Why Script Safety Matters⌗

A poorly written script can cause unintended data loss, infinite loops, or security vulnerabilities. Writing robust scripts ensures they behave predictably and handle errors gracefully.

1. Enabling Safe Bash Options⌗

Bash provides built-in options to catch errors early and prevent common pitfalls.

Add this at the start of your script:

set -euo pipefail

Breakdown of these options:⌗

  • -e : Exit immediately if any command fails.
  • -u : Treat unset variables as errors.
  • -o pipefail : Return the exit status of the first failing command in a pipeline.

Example: Handling unset variables safely⌗

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

echo "Processing file: $filename"

Running this script without defining $filename will trigger an error instead of running with unintended behaviour.

2. Input Validation⌗

Never assume user input is correct. Use read with validation checks.

read -p "Enter a directory path: " dir
if [[ ! -d "$dir" ]]; then
    echo "Error: '$dir' is not a valid directory."
    exit 1
fi

3. Preventing Dangerous Expansions⌗

If handling filenames, always quote variables to prevent issues with spaces or special characters.

Bad example:

rm -rf $dir/*

If $dir is empty, this expands to rm -rf /* - disastrous!

Safe version:

rm -rf "$dir"/*

4. Using Temporary Files Safely⌗

Use mktemp to avoid collisions instead of relying on predictable filenames.

tmpfile=$(mktemp)
echo "Working in $tmpfile"
rm -f "$tmpfile"

5. Handling Errors Gracefully⌗

Use trap to clean up resources on failure.

cleanup() {
    echo "Cleaning up..."
    rm -f "$tmpfile"
}
trap cleanup EXIT

Conclusion⌗

By following these principles, you can make your scripts safer, more reliable, and easier to maintain. Always test your scripts in a safe environment before using them in production.