Date created: Thursday, August 2, 2018 9:02:02 AM. Last modified: Tuesday, November 7, 2023 9:08:44 AM

Bash Notes

Bash style guides:

https://google.github.io/styleguide/shellguide.html

https://github.com/anordal/shellharden/blob/master/how_to_do_things_safely_in_bash.md

https://www.davidpashley.com/articles/writing-robust-shell-scripts/

https://github.com/dylanaraps/pure-bash-bible

 

Debugging

Enabled debugging:

set -x

or

bash -x myscript.sh

 

Print line numbers and variables after they are evaluated:

export PS4="\$LINENO: "
set -xv

 

Perform syntax checking:

bash -n myscript.sh

 

Type checking:

$ type cat
cat is /bin/cat

$ type echo
echo is a shell builtin

$ type if
if is a shell keyword

 

Testing

Syntax testing:

# From: https://www.shellcheck.net/
$sudo apt-get install shellcheck

$shellcheck ./mount_drive.sh

In mount_drive.sh line 3:
if [[ `id -u` -ne 0 ]]
^-----^ SC2006: Use $(...) notation instead of legacy backticked `...`.

Did you mean:
if [[ $(id -u) -ne 0 ]]

 

Errors Handling / Safety

Stop script and error if undefined variables are found. The default is behaviour is to carry on:

set -u

 

Stop the entire script if a command has a non-zero exist status. The default behaviour is to carry on:

set -e

To override this for a specific command or function call (e.g. one with a non-zero exist status on success) append the following:

my_function || true

Disable error checking:

set +e

 

By default when using piped commands (echo "hi" | grep "h" | wc -l) only the exit status of the last command is evaluated. With set -e, only if the last command in the pipe has a non-zero exist status would the script exit. The following option causes a non-zero exit status from any of the commands in a pipe series to return non-zero for the entire pipe series. Together with set -e it causes a script to error out if any command has a non-zero exist status (including commands in the middle of a pipe series).

set -o pipefail

To temporarily disable pipe fail:

set +o pipefail

 

Disable filename expansion (globbing) upon seeing *, ?, etc.

set -f

If a script depends on globbing then this shouldn't be set. Instead the following can be used, which causes globs that don't get expanded to raise an error, rather than getting passed to the command with the * intact:

shopt -s failglob

 

 

Traps

A collapsed stack trace (using caller()) that can be run on error/exit:

onerr (){ while caller $((n++)); do :; done; }
trap onerr ERR
trap onerr EXIT

 

Run a clean-up function:

function finish {
# cleanup code here
}
trap finish EXIT
trap finish SIGQUIT

 

 

Escaping Strings:

$ # This string 'has single' "and double" quotes and a $
$ !:q:p
'# This string '\''has single'\'' "and double" quotes and a $'

$ printf '%q' 'This string has do"uble quotes"'
This\ strin\"g\ has\ double\ quotes\"

 


Previous page: Syscalls On Linux
Next page: Backup Github