CheatSheets/bash_programming.md

5.6 KiB

Start bash files with

#!/usr/bin/env bash

Declare global variables at the beginning of the script. Include a short comment to add context to the variables.

# name of BUP file generated by Nvidia script
BUPFILE="${BUPFILE:-bl_update_payload}"

Create variables that can be overridden

# ORIG_DIR: starting directory where the script will drop the user on exit
ORIG_DIR="${ORIG_DIR:-$(pwd)}"

Properly configured variables can be overridden at execution. For example

wp@host:~/$ ORIG_DIR="My override value" ./my_script.sh

Allow easy debugging early in the script. The following code block will enable easy debugging, which will print each line of code before it is executed

if [ ! -z ${DEV+x} ] && [ "$DEV" -eq "1" ]; then
    # enable early debugging with `DEV=1 build.sh`
    set -x
    PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
else
    set -eu
fi

The script can be debugged by prefixing the script with the correct parameter assignment.

wp@host:~/$ DEV=1 ./my_script.sh

Group functions together under the following banner

#======================================================================================================================
#=====                                                 FUNCTIONS                                                  =====
#======================================================================================================================

Create a header for each function using the following template

#---  FUNCTION  -------------------------------------------------------------------------------------------------------
#          NAME:  __wget
#   DESCRIPTION:  Download if file doesn't exist.
#         USAGE:  __wget [outfile] [url]
#         NOTES:  if [outfile] exists, it will be tested to verify it is a regular file
#----------------------------------------------------------------------------------------------------------------------
__wget() {
    # do stuff
}

For large, complex scripts, create a banner marking the start of execution, such as

#======================================================================================================================
#=====                                                   BEGIN                                                    =====
#======================================================================================================================

Use sub-banners if needed

#----------------------------------------------------------------------------------------------------------------------
#-----                                            Command Line Args                                               -----
#----------------------------------------------------------------------------------------------------------------------

Include a useful help

#---  FUNCTION  -------------------------------------------------------------------------------------------------------
#         NAME:  __usage
#  DESCRIPTION:  Display program help
#        USAGE:  __usage
#----------------------------------------------------------------------------------------------------------------------
__usage() {
    cat << EOT

Usage: ${__SCRIPTNAME} [options] [action]...

Actions:
  - dtb         Build Devicetree binary files
  - blob        Build Mass Flash tool to flash Nano over USB
  - bup         Build Bootloader Update Package
  - tpm         Build the TPM kernel modules
  - tpm-rng     Build the TPM hardware random number generator module
  - pkg         Build the update package to distribute to Nano
  - dev         Enable development (debug) mode. Mainly, disables cleanup of
                temporary files created during program execution
  - all         Same as ${__SCRIPTNAME} dtb bup tpm pkg blob
                Does not build the optional tpm-rng module
  - help        Display usage

Options:
  -h Display this help
  -D Enable debugging mode

Examples:
  - ${__SCRIPTNAME} all
  - ${__SCRIPTNAME} all dev
  - ${__SCRIPTNAME} dtb tpm bup

EOT
}

Common bash test expressions https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html

The following test operators return "True" if the file exists
-a file :: Any file type
-e file :: Any file type
-f file :: Any regular file (ie not a block, socket, pipe, symlink, etc.)
-b file :: Block special file
-c file :: Character file
-d file :: Directory type
-h file :: Symbolic link
-L file :: Symbolic link
-p file :: Named pipe file (FIFO)
-s file :: Socket file

The following operators test existing files for specific properties
-g file :: Any file AND set-group-id bit set
-k file :: Any file AND sticky bit set
-r file :: Any file AND file is readable
-w file :: Any file AND file is writable
-x file :: Any file AND executable bit is set
-s file :: Any file AND file size is greater than 0

Other common test operators
-v varname :: True if 'varname' is set and has been assigned a value
-R varname :: True if varname is set and is a name reference
-n string :: True if length of string is not zero
string1 == string2 :: True if the strings are equal
string1 = string2 :: True if the strings are equal. POSIX conformant
string1 != string2 :: True if the strings are not equal
string1 < string2 :: True if string1 sorts before string2
string1 > string2 :: True if string1 sorts after string2

Arthimetic test operators
arg1 -eq arg2 :: True if arg1 is equal to arg2
arg1 -ne arg2 :: True if arg1 is not equal to arg2
arg1 -lt arg2 :: True if arg1 is less than arg2
arg1 -le arg2 :: True if arg1 is less than or equal to arg2
arg1 -gt arg2 :: True if arg1 is greater than arg2
arg1 -ge arg2 :: True if arg1 is greater than or equal to arg2