BAMF is a library for bash scripts. 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 started as one person's toolkit and grew over many years of production scripting: deployment hooks, CI pipelines, server setup, and the glue between them. Automate the Cloud publishes it for two reasons: so other people can write reliable scripts faster, and to show, in working code, the bash practices that make scripts dependable.
This is the core of examples/hello.sh, with the argument handling and the Initialize section left out:
#!/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 0Running it on a terminal:
When a script runs others, each child's lines use a softer palette and line up under the parent's. When something fails, the exit code says what went wrong, by name, all the way back up. Here examples/pipeline.sh runs two steps, and the second one fails:
Every line names the script that wrote it, so the output of several scripts stays readable when they run one after another in a CI job or a deployment log. Color appears on a terminal; 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])
Timestamps can be turned on for a terminal too, by whoever runs the script (BAMF_ENABLE_TIMESTAMP=yes) or in the script itself (ENABLE_TIMESTAMP=yes):
These images are made from the scripts' real output by ci/readme_images.sh, and CI checks they are current.
- Logging that looks the same in every script: notices, warnings, errors, highlighted sections, file contents with line numbers, and timestamps when the output goes to a file. Each line is a single
printf, with no subshells, so logging stays fast in loops. - Named exit codes.
exit_logic "${E_OBJECT_NOT_FOUND}"exits with 8, and the log saysE_OBJECT_NOT_FOUND / Object not found. Define your own withdefine_exit_code. - A guaranteed ending.
start_logictraps signals and the end of the script, so temporary files are removed and the exit code is logged whether the script finishes, fails underset -e, or is stopped with Ctrl+C. Register your own cleanup withadd_exit_function, and it runs on every one of those paths too. - Temporary files and directories that are removed when the script exits, and only ever from inside the temporary directory.
- Dependency checks before any work starts: list the commands your script needs in
REQUIRED_EXECUTABLES, and it stops withE_MISSING_DEPENDENCIESif one is missing. - Secrets kept out of logs. Option values named in
SENSITIVE_ARGUMENTSare masked in the start line, andgenerate_temp_file_with_contentpasses secrets to commands through a 0600 file instead of the command line, where any user could see them in the process list. - Configuration helpers that read properties, dotenv, key/value, and simple YAML files into variables, and check that required values are set.
- Helper files for specific tools, loaded only by the scripts that need them (see Helper files).
- bash 4.2 or newer. The tests run on bash 4.2 (CentOS 7) and bash 5.2 (Debian 12, Amazon Linux 2023).
- GNU coreutils (
date,mktemp,stat). Alpine and BusyBox are not supported.
Nothing else is needed for the core. A few functions use other common tools when you call them, such as gzip, file, or uuidgen, and say so in their description.
Copy bamf.inc (and any helper files you want) next to your scripts, or anywhere your scripts can find them. There is nothing to install.
A BAMF script follows the same shape every time:
#!/bin/bash
###------------------------------------------------------------------------------------------------
# script: backup.sh
# purpose: Copies the application data to the backup volume
# version: 1.0.0
###------------------------------------------------------------------------------------------------
## Config
SELF_IDENTITY="backup" # optional, defaults to the script's file name
SENSITIVE_ARGUMENTS="p" # values of -p are masked in the log
ARGUMENTS_DESCRIPTION=(
'-s <directory> : Source directory'
'-p <password> : Archive password'
)
## Load BAMF
source "/opt/bamf/bamf.inc" || exit 3
## Dependencies
REQUIRED_EXECUTABLES+=( 'rsync' )
# REQUIRED_SOURCE_FILES+=( aws ) # helper files, by name
## Main
while getopts "hVs:p:" OPTION; do
case "${OPTION}" in
s) DIRECTORY_SOURCE="${OPTARG}";;
p) ARCHIVE_PASSWORD="${OPTARG}";;
h) usage; exit 0;;
V) return_script_version "${0}"; printf '\n'; exit 0;;
*) usage; exit "${E_BAD_ARGS}";;
esac
done
start_logic
line_break
log_highlight "Initialize"
# check arguments and configuration here
line_break
log_highlight "Execution"
# do the work here; on any failure: exit_logic <exit code> "<message>"
log_success "Backup finished"
exit_logic 0-
ShellCheck cannot see that
bamf.increadsSELF_IDENTITYandARGUMENTS_DESCRIPTION, and warns that they are unused (SC2034). Silence it on those lines with# shellcheck disable=SC2034, as the examples do, rather than for the whole file. -
The header comments are read by BAMF.
usageprints the# purpose:and# version:lines, and-Vprints the version. -
start_logiccomes after the arguments are processed, so-hand-Vwork without starting the script. -
Functions return an exit code. Check it and end the script with it:
load_property_from_file DB_HOST db.host "${FILE_CONFIG}" verify_array_key_values "REQUIRED_KEYS[@]" APP || exit_logic $?
-
Functions that produce a value take the name of a variable to put it in, as their first or last argument (each function's description says which). Where that argument is optional, leaving it empty prints the value instead, so
$(trim "${VALUE}")works too.
Set these in the environment when running a script. They override what the script itself sets.
| Variable | What it does |
|---|---|
BAMF_ENABLE_COLOR |
yes or no, to force color on or off. It wins over everything else. Without it, color is off when NO_COLOR is set; otherwise the script's own ENABLE_COLOR decides, and without that, color is on when the output is a terminal. |
BAMF_ENABLE_TIMESTAMP |
yes or no, to force the timestamp at the start of each log line on or off. Without it, the script's own ENABLE_TIMESTAMP decides, and without that, timestamps are on when the output is not a terminal (a log file, CI, cron, CodeDeploy) and off on a terminal. |
BAMF_LOG_IDENTITY_WIDTH |
The width of the [script name] column. Each line is padded with dots to it, so the messages line up. Defaults to the length of the script's name; exec_script passes its width on to the scripts it runs. Set it to line up the logs of several scripts that run separately. |
BAMF_LOG_DATE_FORMAT |
The format of the timestamp on each log line, in strftime form (for example %H:%M:%S, or %Y-%m-%dT%H:%M:%S%z). Defaults to %Y-%m-%d %H:%M:%S. A script can set its own default with LOG_DISPLAY_DATE_FORMAT. |
BAMF_DIRECTORY_TEMPORARY |
Where temporary files are created. Defaults to DIRECTORY_TEMPORARY if the script sets it, then TMPDIR, then /tmp. It must be an absolute path other than /, and it is created if it does not exist. |
NO_COLOR |
Any value turns color off, even in a script that sets ENABLE_COLOR=yes, unless BAMF_ENABLE_COLOR says otherwise. See no-color.org. |
Exit codes are numbers from 0 to 255, so BAMF divides the range:
| Range | Used by |
|---|---|
| 0–80, 251–255 | BAMF core: E_BAD_ARGS (5), E_OBJECT_NOT_FOUND (8), E_MISSING_DEPENDENCIES (7), and others |
| 81–120, 151–200 | BAMF core and helper files |
| 121–150 | bash itself and signals: 127 command not found, 130 Ctrl+C, 143 terminated |
| 201–250 | Your scripts |
Define your own, and the log will name them:
define_exit_code E_BACKUP_VOLUME_FULL 201 "The backup volume is full"
exit_logic "${E_BACKUP_VOLUME_FULL}"
# SCRIPT_FINISHED: (Duration::0m 01.204s / Exit_Code::201 [E_BACKUP_VOLUME_FULL / The backup volume is full])E_SUCCESS_ALT (251) is for a script that succeeded but must still return a non-zero code, for example to tell a scheduler that there was nothing to do.
bamf.inc is everything most scripts need. For work tied to one tool or service, the helpers directory holds optional helper files, bamf.<name>.inc, that a script loads only when it uses them:
REQUIRED_SOURCE_FILES+=( aws docker ) # helpers/bamf.aws.inc, then helpers/bamf.docker.inc
start_logicThere are helpers for AWS, curl, Docker, Git, npm, package management, tar, and Terraform. helpers/README.md describes each one, how to write your own, and every function they provide.
BAMF is meant to be read as well as used. These are the techniques in it that are worth knowing for any bash script, and where to find them.
- Return values with
printf -v, nevereval.printf -v "${NAME}" '%s' "${VALUE}"stores any value in the variable named by the caller, exactly as it is. The common alternative,eval ${NAME}="'${VALUE}'", runs the value as code, so a quote in a value read from a file can run commands. See_bamf_return. - Print with
printf '%s', notecho.echotreats a value of-nor-eas an option and, depending on the shell, interprets backslashes.printf '%s'prints the value as it is. command -vinstead ofwhich.whichis a separate program that some minimal images, including Amazon Linux 2023, do not install.command -vis part of bash.- Cleanup in an
EXITtrap. A trap onEXITruns however the script ends.exit_trap_ensure_gracefuluses it so a script that forgetsexit_logic, or stops on an error underset -e, still cleans up and reports its exit code. - Delete only what you created.
cleanupremoves only the filesgenerate_temp_filerecorded, and refuses anything outside the temporary directory, so a bad variable can never turn it intorm -rf /. - Keep secrets off the command line. On most systems, every user on the machine can see a command's arguments with
ps. Write a secret to a 0600 file and pass the file instead, asgenerate_temp_file_with_contentdoes. - Works under
set -euo pipefail. Every optional argument is read as${1:-}, so the library works in scripts that treat unset variables as errors. Empty arrays are expanded as"${ARRAY[@]+"${ARRAY[@]}"}", because before bash 4.4,"${ARRAY[@]}"on an empty array is an unbound variable error underset -u. - Guard every removal.
rm -rf "${DIRECTORY}/${NAME}"becomesrm -rf /if both variables are empty."${DIRECTORY:?}/${NAME:?}"makes bash stop with an error instead. BAMF uses it wherever a path built from variables is removed. - A failed
$(...)assignment ends aset -escript.WIDTH="$(tput cols)"fails when there is no terminal type, as under cron, CI, and in containers. Give such assignments a fallback:WIDTH="$(tput cols)" || WIDTH="". - Know the oldest bash you support. In bash 4.2,
declare -gA NAME=()inside a function creates the global array, but later assignments do not reach it. Declaring first and assigning separately works in every version. The tests run on bash 4.2 to catch differences like this one. - Read files with
while IFS= read -r LINE || [[ -n "${LINE}" ]].IFS=keeps leading spaces,-rkeeps backslashes, and the||test keeps a last line that has no newline at the end.
The examples directory holds complete scripts. Each teaches one idea, explains it in its comments, and is run by the test suite, so it keeps working.
| Example | What it shows |
|---|---|
hello.sh |
The shape of a BAMF script: arguments, logging, a temporary file, and exit codes |
config_check.sh |
Reading a configuration file, checking every required value at once, your own exit code, and handing values to a CI pipeline |
pipeline.sh |
One script running others in order, with a failing step's exit code traveling back |
cleanup_and_signals.sh |
Cleanup that runs however the script ends: success, an error under set -euo pipefail, or Ctrl+C (add_exit_function) |
download_verify.sh |
Downloading with retries, checking a SHA-256 checksum before using the file, and extracting it |
backup_to_s3.sh |
Archiving a directory, encrypting it with a KMS key, and uploading it to S3 |
codedeploy/ |
A complete set of AWS CodeDeploy hooks for a containerized application: settings from SSM Parameter Store, Docker Compose, and a health check that stops a bad deployment |
Contributions are welcome, after review. Read CONTRIBUTING.md before opening a pull request, and report security problems as described in SECURITY.md.
The tests use bats-core, and the code is checked with ShellCheck. The CI scripts download pinned versions of both:
ci/install_test_dependencies.sh
ci/lint.sh
ci/test.sh # with your bash
ci/test.sh centos:7 debian:12-slim amazonlinux:2023 # in containers, with DockerEvery function in bamf.inc, generated from the comments in the code (ci/function_reference.sh -u updates it). The helper files' functions are in helpers/README.md.
BASH Application Management Framework (BAMF) core library
| Function | What it does | Arguments |
|---|---|---|
add_element_to_array |
Appends one or more elements to the array with the specified name | $1 Array Name$2+ Element(s) |
add_exit_function |
Registers a function to run when the script exits, however it exits: exit_logic, an error under set -e, the end of the script, or a signal such as Ctrl+C. Use it to undo what the script set up outside the machine's temporary directory (a lock, a DNS record, a test resource in the cloud). Functions run once each, the last registered first, before the temporary files are removed; BAMF_EXIT_CODE holds the code the script is exiting with. A failing function is logged and does not change the exit code. Requires start_logic, which sets up the exit handling |
$1 Function name |
base64_decode |
Decodes a base64 string | $1 Variable name to pass info to (optional, if not specified the decoded string is printed)$2 Encoded string |
base64_encode |
Encodes a string to base64 (single line, the string is encoded exactly as given) | $1 Variable name to pass info to (optional, if not specified the encoded string is printed)$2 String |
base64_encode_and_compress |
Compresses a string (gzip -9) and encodes the result to base64 (single line) Decode with: printf '%s' "${STRING}" | base64 -d | gunzip Returns E_MISSING_DEPENDENCIES if gzip is not installed |
$1 Variable name to pass info to (optional, if not specified the encoded string is printed)$2 String |
call_sleep |
Sleeps for the specified number of seconds and logs it | $1 Number of seconds to sleep$2 Reason (optional) |
call_sleep_random |
Sleeps for a random number of seconds between 1 and the specified maximum, and logs it | $1 Max sleep time in seconds (optional, defaults to 60; 0 does not sleep) |
cleanup |
Removes the temporary files and directories created by generate_temp_file / generate_temp_directory Only removes entries located beneath the temporary directory (or /tmp); anything else is skipped with a warning, for safety |
none |
cleanup_quiet |
Same as cleanup, without logging | none |
color_lookup |
Prints the color definition for a color name (an unknown name is printed back unchanged) | $1 color name (example: light_cyan) |
color_text |
Prints text gently swaddled in radiant color The text is printed as-is (backslash sequences in the text are not interpreted) When color is disabled (ENABLE_COLOR), the text is printed without color codes |
$1 color (example: "${COLOR_YELLOW}" or "$(color_lookup yellow)")$2 text$3 color to resume (optional, defaults to the log message color) |
debug_color_text |
Prints a test line in each of the defined colors (for debug purposes only) | none |
define_exit_code |
Defines a named exit code (declares the variable and registers it for lookup_exit_code) Returns E_BAD_ARGS for an invalid definition, E_OBJECT_ALREADY_EXISTS if the number is used by another name |
$1 Name (must start with E_, example: E_MY_FAILURE)$2 Number (0-255)$3 Description (optional) |
does_array_contain_element |
Returns true if the array contains the element | $1 Element string to search for$2+ Array (pass this way: "${array[@]}") |
echo_key_value |
Prints a [key]=value line, the format read by load_key_value_from_file (the key is lowercased) | $1 key$2 value |
exec_script |
Runs another script as a child (inception?), which logs in the child color palette Returns the exit code of the script that was run |
$1 Script to run$2+ Arguments to pass to the script |
exit_logic |
Ends the script: removes temporary files, logs the duration and exit code, restores the terminal An exit code given but empty (exit_logic "${E_MISTYPED}") ends the script with E_UNKNOWN_EXIT_CODE, not 0: an unset variable must never turn a failure into a success. Quote the code, as in exit_logic "${E_BAD_ARGS}", so this check can see it; unquoted, an empty value disappears. |
$1 Exit code to return (optional, defaults to 0)$2 Exit message (optional) |
exit_logic_quiet |
Same as exit_logic, without logging | $1 Exit code to return (optional, defaults to 0) |
exit_logic_skip_cleanup |
Same as exit_logic, but leaves the temporary files in place (useful for debugging) | $1 Exit code to return (optional, defaults to 0)$2 Exit message (optional) |
exit_trap |
Exit logic for a caught signal (set up by start_logic) | $1 Exit code to return$2 Exit message (optional) |
exit_trap_ensure_graceful |
Exit logic for the EXIT trap (set up by start_logic) A safety net for a script that ends without calling exit_logic (or that stops on an error under set -e): the temporary files are still removed and the exit code is still logged |
none |
explode_key_value_to_file |
Writes each element of a delimited string to a file as a [key]=value line An element without "=" is written with the value "true" |
$1 File to write to$2 Delimited string (example: "name=web;port=443;debug")$3 Delimiter (optional, defaults to ";") |
file_update_owner |
Changes the owner of a file or directory | $1 File or directory$2 Owner (example: apache:apache) |
file_update_permissions |
Changes the permissions of a file or directory | $1 File or directory$2 Permissions (example: 0400) |
filesize_bytes_to_human_readable |
Converts a size in bytes to a human readable format (example: 1.50 MB) | $1 Size in bytes (integer)$2 Variable name to pass info to (optional, if not specified the value is printed) |
function_exists |
Returns true if a function with the specified name exists | $1 Function name |
generate_temp_directory |
Creates a temporary directory, which cleanup removes when the script exits Exits the script (E_OBJECT_FAILED_TO_CREATE) if the directory cannot be created |
$1 Variable name to pass the directory name to$2 Purpose string (optional, shown in the log on failure)$3 Base directory (optional, defaults to DIRECTORY_TEMPORARY) |
generate_temp_file |
Creates a temporary file (mode 0600), which cleanup removes when the script exits Exits the script (E_OBJECT_FAILED_TO_CREATE) if the file cannot be created |
$1 Variable name to pass the file name to$2 Purpose string (optional, shown in the log on failure)$3 Directory (optional, defaults to DIRECTORY_TEMPORARY) |
generate_temp_file_with_content |
Creates a temporary file (mode 0600) holding the content exactly as given (no newline added) Use it to pass sensitive values to commands as file:// or fileb:// arguments, so they do not appear in the process list |
$1 Variable name to pass the file name to$2 Content$3 Purpose string (optional) |
generate_uuid |
Creates a random UUID, lowercase and without hyphens | $1 Variable name to pass info to (optional, if not specified the value is printed)$2 Length (optional, truncates the 32 character string) |
is_empty |
Returns true if the value is empty With strict checking (the default), the values 0 and 0.0 also count as empty |
$1 Value to check$2 Strict checking, yes or no (optional, defaults to yes) |
is_int |
Returns true if the value is an integer (an optional leading minus sign, then digits) | $1 Value to check |
is_running_as_root |
Returns true if the script is running as root | none |
is_server_up |
Returns true if the server answers ping (3 attempts) | $1 Server address |
json_escape |
Prints a string escaped for use inside a JSON string value (the surrounding quotes are not added) Escapes backslashes, double quotes and control characters, so any value can be placed in JSON built by a script: printf '{"name": "%s"}' "$(json_escape "${NAME}")" |
$1 String |
json_extract_from_string |
Extracts the value of a key from a simple JSON string Works best on flat JSON objects that do not repeat key names; for anything more complex, use a JSON tool such as jq. This exists so simple cases do not need jq installed. |
$1 Variable name to pass info to (optional, if not specified the value is printed)$2 Key name$3 JSON string |
json_safe |
Prints the string with characters that would break a JSON string value replaced Newlines, single and double quotes become underscores; surrounding spaces are removed; non-ASCII characters are removed when iconv is available |
$1 String |
line_break |
Prints a line that spans the full width of the terminal Serves no purpose other than to be a pretty, pretty princess The width is looked up on first use and cached for the life of the script |
none |
load_array_key_values_from_file |
For each key in the array, loads its value from a [key]=value file into an uppercase variable Example: keys ('region') with prepend string APP set APP_REGION |
$1 Array (pass this way: "KEYS[@]")$2 File to load from$3 Prepend String (optional, an underscore is added automatically)$4 Parse String (optional, see load_key_value_from_file) |
load_array_key_values_from_yaml_file |
For each key in the array, loads its value from a YAML file into an uppercase variable See return_yaml_string for the (simple) YAML that is understood |
$1 Array (pass this way: "KEYS[@]")$2 File to load from$3 Prepend String (optional, an underscore is added automatically) |
load_array_properties_from_file |
For each key in the array, loads its value from a properties file into an uppercase variable Example: keys ('db.host') with prepend string APP set APP_DB_HOST |
$1 Array (pass this way: "KEYS[@]")$2 File to load from$3 Prepend String (optional, an underscore is added automatically) |
load_key_value_from_file |
Loads a value from a file of [key]=value lines (written by write_key_value_to_file) With a parse string, reads [parse][key]=value lines instead The key is matched exactly; when a key appears more than once, the last line wins |
$1 Variable name to pass info to (optional, if not specified the value is printed)$2 Key name$3 File$4 Parse String (optional) |
load_property_from_file |
Loads a value from a properties or dotenv style file (key=value lines) Keys match without regard to case, and "." and "_" are interchangeable (db.host matches DB_HOST) Spaces around "=" and a leading "export " are allowed; lines starting with # or ! are comments Matching single or double quotes around the value are removed; when a key appears more than once, the last line wins |
$1 Variable name to pass info to (optional, if not specified the value is printed)$2 Key name$3 File |
log |
Prints a log line: [identity] message, with the name padded with dots to the width of the name column, so messages line up (see LOG_IDENTITY_WIDTH); a timestamp comes first when ENABLE_TIMESTAMP is on | $1 Message$2 Message type (optional): NOTC notice, SUCC success, WARN warning, ERRO error, HIGH highlight, SSTR script start, SFIN script finished, SNFO script info, FILE file content, SCLI command line, QUIE quiet (not printed)$3 Message color override (optional) |
log_add_from_file |
Prints the content of a file to the log, with line numbers | $1 File$2 Description of the contents (optional)$3 Maximum number of lines to print (optional, defaults to 1000) |
log_error |
Prints an error log line (prefixed with "ERROR: ") | $1 Message$2 Message color override (optional) |
log_file_content |
Prints a single line of file content (line number 0 prints a separator line) | $1 Line number$2 Line content |
log_highlight |
Prints a highlighted log line: [[ message ]] | $1 Message |
log_load_color_child |
Loads the color palette for scripts run by another script (see exec_script) | none |
log_load_color_parent |
Loads the color palette for scripts run directly | none |
log_notice |
Prints a notice log line | $1 Message$2 Message color override (optional) |
log_quiet |
Prints nothing (a placeholder for messages that are only useful while debugging) | $1 Message |
log_status |
Prints a status log line: [identity] [PASS] message PASS and SUCCESS are shown in the success color, FAIL and ERROR in the error color, anything else in the warning color |
$1 Status (example: PASS)$2 Message$3 Width to pad the [STATUS] to with dots, so statuses of different lengths line up (optional, defaults to no padding; 9 fits [SUCCESS] and [WARNING])$4 Message color override (optional) |
log_success |
Prints a success log line (prefixed with "SUCCESS: ") | $1 Message$2 Message color override (optional) |
log_warning |
Prints a warning log line (prefixed with "WARNING: ") | $1 Message$2 Message color override (optional) |
lookup_exit_code |
Prints the name and description of an exit code (example: E_BAD_ARGS / Bad or missing arguments) Prints UNKNOWN for a code that has not been defined with define_exit_code |
$1 Exit code |
option_enabled |
Returns true if the variable with the specified name is set to y, yes, 1 or true (any case) Usage: "if option_enabled VERBOSE; then" - NOTE: the argument is the variable name, not the variable (no $) |
$1 Variable name |
parse_yaml |
Prints a simple YAML file as name="value" lines, nested keys joined with underscores (example: "db:\n host: x" prints db_host="x") Handles maps of scalars indented by two spaces; lists and multi-line values are not supported |
$1 File to parse |
parse_yaml_to_file |
Writes the output of parse_yaml to a file | $1 File to parse$2 Output file |
return_file_last_modify_timestamp |
Returns the last modification time of a file (UNIX timestamp) Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_file_md5sum |
Returns the MD5 checksum of a file Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_file_mime |
Returns the MIME type of a file (requires the file command) Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_file_sha1sum |
Returns the SHA-1 checksum of a file Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_file_sha256sum |
Returns the SHA-256 checksum of a file Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_filesize_of_file |
Returns the size of a file in a human readable format (example: 1.50 MB) Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_filesize_of_file_in_bytes |
Returns the size of a file in bytes Returns E_OBJECT_NOT_FOUND (and an empty value) if the file does not exist |
$1 File$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_header_string |
Returns the value of a "# : " comment line from a file (the first one found) Example: return_header_string version "${0}" prints the "# version:" line of the script |
$1 Header identifier$2 File$3 Variable name to pass info to (optional, if not specified the value is printed) |
return_hostname |
Returns the host name | $1 Variable name to pass info to (optional, if not specified the value is printed) |
return_parameter_string |
Returns the value of a "## : " comment line from a file (the first one found) | $1 Parameter identifier$2 File$3 Variable name to pass info to (optional, if not specified the value is printed) |
return_script_purpose |
Prints the "# purpose:" header of a script ("unknown" if it has none) A .info file next to the script is read instead, when it exists |
$1 File (normally "${0}") |
return_script_version |
Prints the "# version:" header of a script ("unknown" if it has none) A .info file next to the script is read instead, when it exists |
$1 File (normally "${0}") |
return_variable_value |
Returns the value of the variable with the specified name, with runs of whitespace collapsed to a single space, without evaluating code or expanding globs Returns E_BAD_ARGS (and an empty value) if the name is not a valid variable name |
$1 Variable name$2 Variable name to pass info to (optional, if not specified the value is printed) |
return_yaml_string |
Returns the value of a "key: value" line from a YAML file (the first one found, at any indent) Matching quotes around the value are removed. Nested keys are not distinguished; use parse_yaml for those |
$1 Variable name to pass info to (optional, if not specified the value is printed)$2 Key$3 File |
run_silently |
Runs a command or function with its output hidden; the output is printed only if it fails Variables set by a function run this way are kept (it does not run in a subshell) If the command ends the script (for example through exit_logic), its output is not shown Returns the exit code of the command |
$1+ Command and its arguments |
source_include |
Loads a file with source (once; a file that is already loaded is skipped) A name without a slash loads a BAMF helper file: "aws" (or "bamf.aws.inc") loads bamf.aws.inc from the helpers directory next to bamf.inc, or from beside bamf.inc when the files are kept together Exits the script (E_OBJECT_NOT_FOUND) if the file does not exist Helper files are sourced inside this function: they must declare their variables with "declare -g" (a plain "declare" or "local" would be local to this function) |
$1 File or helper name |
start_logic |
Starts the script; call it once, after processing the arguments Logs the start line (the command line, with SENSITIVE_ARGUMENTS masked) Sets traps so the script always ends through exit_logic (signals, errors under set -e, or reaching the end of the script) Loads the files listed in REQUIRED_SOURCE_FILES, in order Checks that the commands listed in REQUIRED_EXECUTABLES exist (exits with E_MISSING_DEPENDENCIES) |
none |
start_logic_quiet |
Same as start_logic, without the start log line | none |
sync_disks |
Flushes file system buffers (sync) and logs it | none |
time_elapsed |
Prints the time elapsed between two timestamps in microseconds (example: 1m 05.250s) | $1 Start time (microseconds since the epoch, from: date +%s%6N)$2 End time (optional, defaults to now) |
timestamp_to_human_readable |
Prints a UNIX timestamp as YYYY-MM-DD HH:MM:SS TZ Only the first 10 digits are used, so timestamps with subseconds (date +%s%6N) work too |
$1 UNIX timestamp$2 Force UTC, yes or no (optional, defaults to no) |
to_lower |
Prints a string in lowercase | $1 String |
to_upper |
Prints a string in uppercase | $1 String |
trim |
Prints a string with spaces removed from both ends (of each line, for a multi-line string) | $1 String |
uptime_greater_than |
Returns true if the system has been up for longer than the specified number of seconds (Linux) | $1 Seconds (optional, defaults to 300) |
usage |
Prints the help: usage banner, ARGUMENTS_DESCRIPTION entries and the common arguments | none |
usage_banner |
Prints the usage banner of a script (name, "# purpose:" and "# version:" headers) | $1 File (normally "${0}") |
usage_normalized_arguments |
Prints the arguments every BAMF script is expected to support | none |
verbose_display_date |
Prints a log date timestamp truncated to YYYY-MM-DD HH:MM:SS | $1 Timestamp |
verify_array_key_values |
Checks that the variable for each key in the array is set and not empty (logs a warning for each one that is not) Example: keys ('region') with prepend string APP check APP_REGION Returns E_OBJECT_NOT_FOUND if any is missing |
$1 Array (pass this way: "KEYS[@]")$2 Prepend String (optional, an underscore is added automatically) |
verify_dependencies |
Checks that every command in REQUIRED_EXECUTABLES can be found in the PATH Exits the script (E_MISSING_DEPENDENCIES) if any is missing |
none |
version_to_integer |
Converts a version string of up to four numbers (example: 1.2.3 or 2.4.10-1) to an integer that sorts the same way, each part up to 999 | $1 Version string$2 Variable name to pass info to (optional, if not specified the value is printed) |
write_dotenv_value |
Appends a NAME=VALUE line to a dotenv file dotenv files are read by most CI systems (GitLab artifacts reports dotenv, GitHub Actions GITHUB_ENV / GITHUB_OUTPUT, Jenkins readProperties) |
$1 dotenv file$2 Variable name$3 Variable value |
write_key_value_to_file |
Appends a [key]=value line to a file (read it back with load_key_value_from_file) | $1 File$2 Key$3 Value |
BAMF is licensed under the Apache License 2.0. See NOTICE for the copyright notice.
The BAMF and Automate the Cloud names and logos, including everything in brand_kit/, are not covered by this license. See brand_kit/NOTICE.md.
Maintained by Automate the Cloud, a Kentucky 501(c)(3) that teaches cloud infrastructure and helps nonprofits run theirs.