x.sh
x.sh - eXtended baSH - call stack and logging for Bash scripts
These utils makes debugging and running complex bash scripts (which nobody should have, but we all end up having anyway) easy and pretty.
- Download the latest version using your favourite CLI web client:
wget https://raw.githubusercontent.com/ultralightweight/x.sh/master/src/x.sh
curl https://raw.githubusercontent.com/ultralightweight/x.sh/master/src/x.sh > x.sh
- Sourcing the file into your script
Source the file in your script to enable strict mode and call stack printing upon error.
source x.sh
Sourcing the script will automatically enable bash strict mode using:
set -E -uo pipefail
Strict mode means that bash scripts will fail at first error and not proceed further. Errors include any commands returning non-zero exit codes outside of if condition blocks, and referencing un-set variables.
Sourcing the script will automatically install the exception trap that produces python-like call stacks upon error.
Consider the following example:
#!/bin/bash
source ../src/x.sh
function some_func() {
echo "hey!"
non_exitent_command
}
function some_other_func() {
echo "hello world, let's call some function"
some_func
}
some_other_func
There is an error in some_func, and it will be called indirectly. Running the above script with trigger an error, and the error trap in x.sh will print a python-like call-stack:
$ ./test/callstack.test.sh
hello world, let's call some function
hey!
./callstack_test.sh: line 7: non_exitent_command: command not found
-----------------------------------------------------
Traceback (most recent call last):
File "./callstack.test.sh", line 16, in main
some_other_func
File "./callstack.test.sh", line 13, in some_other_func
some_func
File "./callstack.test.sh", line 7, in some_func
non_exitent_command
error in ./callstack.test.sh line 7, command `non_exitent_command` returned 127
Why do we need logging in bash? Logging in bash is just as easy as calling echo, so why bother?
Well, these logging functions in x.sh will create a python-like log record, with timestamp, log level, and automatic inclusion of where the log came from. For example:
#!/bin/bash
source ../src/x.sh
function some_func() {
x-log-info "Hello from here!"
for i in 1 2 3 4 5; do
x-log-debug "Doing step $i"
done
x-log-error "Huston, we got trouble!"
}
function some_other_func() {
x-log-info "Starting something..."
some_func
x-log-warning "Thing might have not gone well..."
}
some_other_func
Running the test will generate the following output:
$ ./test/logger_test.sh
2020-07-08 08:33:10.202 INFO logger_test.sh:some_other_func Starting something...
2020-07-08 08:33:10.206 INFO logger_test.sh:some_func Hello from here!
2020-07-08 08:33:10.209 ERROR logger_test.sh:some_func Huston, we got trouble!
2020-07-08 08:33:10.213 WARNING logger_test.sh:some_other_func Thing might have not gone well...
Notice that debug logs are not visible. Debug log lines are hidden unless debug mode is enabled by setting the XSH_DEBUG environment variable to a non-empty value. For example:
[dev@uldevbox test]$ export XSH_DEBUG=1; ./logger_test.sh
2020-07-08 08:36:25.377 INFO ./logger_test.sh:some_other_func:15 Starting something...
2020-07-08 08:36:25.380 INFO ./logger_test.sh:some_func:6 Hello from here!
2020-07-08 08:36:25.382 DEBUG ./logger_test.sh:some_func:8 Doing step 1
2020-07-08 08:36:25.384 DEBUG ./logger_test.sh:some_func:8 Doing step 2
2020-07-08 08:36:25.386 DEBUG ./logger_test.sh:some_func:8 Doing step 3
2020-07-08 08:36:25.388 DEBUG ./logger_test.sh:some_func:8 Doing step 4
2020-07-08 08:36:25.390 DEBUG ./logger_test.sh:some_func:8 Doing step 5
2020-07-08 08:36:25.392 ERROR ./logger_test.sh:some_func:10 Huston, we got trouble!
2020-07-08 08:36:25.395 WARNING ./logger_test.sh:some_other_func:17 Thing might have not gone well...
The ERROR and WARNING records are written to stderr, all other lines are written stdout. For example, redirecting stdout to /dev/null would only display us errors:
[dev@uldevbox test]$ export XSH_DEBUG=1; ./logger_test.sh > /dev/null
2020-07-08 08:37:20.053 ERROR ./logger_test.sh:some_func:10 Huston, we got trouble!
2020-07-08 08:37:20.055 WARNING ./logger_test.sh:some_other_func:17 Thing might have not gone well...
Feedback and pull requests are always welcome!
This library is available under MIT Licence.