First up - here’s the template. Continue reading below for an explanation of each component.

Unofficial Strict Mode

set -euo pipefail
IFS=$'\n\t'

There’s a few things going on here -

  • set -e will exit the script if any command returns a non-zero status.
  • set -u will stop a script if using an undefined variable.
  • set -o pipefail will terminate the script at the first failed command in a pipeline.
  • IFS=$'\n\t' makes iterating over lines more predictable by splitting on new lines and tabs, rather than spaces.

Logging Helpers

This template provides helpers for displaying log messages at various levels. These levels provide more context for users of the script. fatal has special behavior where it will exit the script with after displaying the message.

  • info "starting script"
  • warning "file missing"
  • error "could not restart service foo"
  • fatal "this script must run as root"

Cleanup

cleanup() {
  info "... cleaned up"
}
trap cleanup EXIT

This pattern ensures the cleanup function is called when the script terminates. This allows you to clean up temporary files, restart services, or provide feedback to the user.

Built-in Documentation

Calling the script with --help flag triggers the help text to display. Fill out the comment block at the top to describe how to use your script.

./add-user-to-group.sh --help

Usage:        ./add-user-to-group.sh [user] [group]
Description:  Adds a user to a group. Requires root.
Examples:     ./add-user-to-group.sh apache www-data
Options:
  --help: Display this help message

More Best Practices

This template was adapted from this excellent blog post Shell Scripts Matter. I highly recommend having a read of this article to get more tips on shell script best practices.