BAMF

The BASH Application Management Framework. You source one file, bamf.inc, and your script gets consistent logging, named exit codes, temporary files that are always cleaned up, dependency checks, signal handling, and a set of everyday helpers for strings, files, and configuration.

It grew over many years of production scripting: deployment hooks, CI pipelines, server setup, and the glue between them. We publish it so other people can write reliable scripts faster, and to show, in working code, the bash practices that make scripts dependable.

A quick look

The core of the hello.sh example:

#!/bin/bash
# purpose: A first BAMF script: logging, a temporary file, and a clean exit
# version: 1.0.0

SELF_IDENTITY="hello"
source "$(dirname "${BASH_SOURCE[0]}")/../bamf.inc" || exit 3

start_logic

line_break
log_highlight "Execution"
log "Hello, ${NAME}"

# Removed automatically when the script exits, however it exits
generate_temp_file FILE_GREETING "greeting"
printf 'Hello, %s\nfrom %s\n' "${NAME}" "$(return_hostname)" > "${FILE_GREETING}"
log_add_from_file "${FILE_GREETING}" "greeting"

log_success "Said hello"
exit_logic 0

Every log line names the script that wrote it, so the output of several scripts stays readable in a CI job or a deployment log. On a terminal the lines are in color; in a log file, CI job, or cron mail, each line gets a timestamp instead:

2026-10-22 14:16:38 [hello] SUCCESS: Said hello
2026-10-22 14:16:38 [hello] SCRIPT_FINISHED: (Duration::0m 00.021s / Exit_Code::0 [success])

What you get

  • Logging that looks the same in every script: notices, warnings, errors, highlighted sections, and file contents with line numbers.
  • Named exit codes. exit_logic "${E_OBJECT_NOT_FOUND}" exits with 8, and the log says E_OBJECT_NOT_FOUND / Object not found. Define your own with define_exit_code.
  • A guaranteed ending. Temporary files are removed and the exit code is logged whether the script finishes, fails under set -e, or is stopped with Ctrl+C. Register your own cleanup with add_exit_function.
  • Dependency checks before any work starts, so a missing command stops the script cleanly instead of halfway through.
  • Secrets kept out of logs, and passed to commands through a private file instead of the command line, where any user could see them.
  • Configuration helpers that read properties, dotenv, key/value, and simple YAML files.
  • Optional helper files for AWS, curl, Docker, Git, npm, package management, tar, and Terraform, loaded only by the scripts that need them.

Getting started

There is nothing to install. Copy bamf.inc, and any helper files you want, next to your scripts. It needs bash 4.2 or newer and GNU coreutils; the tests run on bash 4.2 (CentOS 7) and bash 5.2 (Debian 12, Amazon Linux 2023).

The repository’s README walks through the shape every BAMF script follows, the configuration settings, how exit codes are numbered, and every function.

Learn from it

BAMF is meant to be read as well as used. Its README explains the techniques in it that are worth knowing for any bash script, and where to find them in the code: returning values with printf -v instead of eval, cleaning up in an EXIT trap, guarding every rm -rf built from variables, keeping secrets out of the process list, and working under set -euo pipefail on every bash back to 4.2.

The examples each teach one idea and are run by the test suite, so they keep working. They range from a first script to reading and checking a configuration file, downloading and verifying a file, backing up to S3 with a KMS key, and a complete set of AWS CodeDeploy hooks for a containerized application.

BAMF is licensed under the Apache License 2.0. The BAMF name and logo are not licensed.