This is the fourth epidose of a small series.
Description:
Support different logging levels natively in your scripts so that your code will be more stable and maintainable.
BAD:
1 2 3 4 5 6 7 |
#!/bin/bash -l ... # for debug only, comment out when OK echo $a do_something $a # echo $? # sometimes does not work? |
GOOD:
Nothing to invent, there are already a few blog posts around about the best practices for log messages. I personally like the one from Michael Wayne Goodman:
http://www.goodmami.org/2011/07/04/Simple-logging-in-BASH-scripts.html
I have reused his code in my scripts with very few modifications to fit my needs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
### verbosity levels silent_lvl=0 crt_lvl=1 err_lvl=2 wrn_lvl=3 ntf_lvl=4 inf_lvl=5 dbg_lvl=6 ## esilent prints output even in silent mode function esilent () { verb_lvl=$silent_lvl elog "$@" ;} function enotify () { verb_lvl=$ntf_lvl elog "$@" ;} function eok () { verb_lvl=$ntf_lvl elog "SUCCESS - $@" ;} function ewarn () { verb_lvl=$wrn_lvl elog "${colylw}WARNING${colrst} - $@" ;} function einfo () { verb_lvl=$inf_lvl elog "${colwht}INFO${colrst} ---- $@" ;} function edebug () { verb_lvl=$dbg_lvl elog "${colgrn}DEBUG${colrst} --- $@" ;} function eerror () { verb_lvl=$err_lvl elog "${colred}ERROR${colrst} --- $@" ;} function ecrit () { verb_lvl=$crt_lvl elog "${colpur}FATAL${colrst} --- $@" ;} function edumpvar () { for var in $@ ; do edebug "$var=${!var}" ; done } function elog() { if [ $verbosity -ge $verb_lvl ]; then datestring=`date +"%Y-%m-%d %H:%M:%S"` echo -e "$datestring - $@" fi } |
The edumpvar is handy to have the status of several variables at once:
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/bin/bash -l # code #... verbosity=6 edumpvar ORACLE_SID ORACLE_HOME <output> 2016-03-15 23:06:10 - DEBUG --- ORACLE_SID=orcl12c 2016-03-15 23:06:10 - DEBUG --- ORACLE_HOME=/u01/app/oracle/product/12.1.0.2 </output> |
If you couple the verbosity level with input parameters you can have something quite clever (e.g. -s for silent, -V for verbose, -G for debug). I’m putting everything into one single snippet just as example, but as you can imagine, you should seriously put all the fixed variables and functions inside an external file that you will systematically include in your scripts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#!/bin/bash -l colblk='\033[0;30m' # Black - Regular colred='\033[0;31m' # Red colgrn='\033[0;32m' # Green colylw='\033[0;33m' # Yellow colpur='\033[0;35m' # Purple colrst='\033[0m' # Text Reset verbosity=4 ### verbosity levels silent_lvl=0 crt_lvl=1 err_lvl=2 wrn_lvl=3 ntf_lvl=4 inf_lvl=5 dbg_lvl=6 ## esilent prints output even in silent mode function esilent () { verb_lvl=$silent_lvl elog "$@" ;} function enotify () { verb_lvl=$ntf_lvl elog "$@" ;} function eok () { verb_lvl=$ntf_lvl elog "SUCCESS - $@" ;} function ewarn () { verb_lvl=$wrn_lvl elog "${colylw}WARNING${colrst} - $@" ;} function einfo () { verb_lvl=$inf_lvl elog "${colwht}INFO${colrst} ---- $@" ;} function edebug () { verb_lvl=$dbg_lvl elog "${colgrn}DEBUG${colrst} --- $@" ;} function eerror () { verb_lvl=$err_lvl elog "${colred}ERROR${colrst} --- $@" ;} function ecrit () { verb_lvl=$crt_lvl elog "${colpur}FATAL${colrst} --- $@" ;} function edumpvar () { for var in $@ ; do edebug "$var=${!var}" ; done } function elog() { if [ $verbosity -ge $verb_lvl ]; then datestring=`date +"%Y-%m-%d %H:%M:%S"` echo -e "$datestring - $@" fi } OPTIND=1 while getopts ":sVG" opt ; do case $opt in s) verbosity=$silent_lvl edebug "-s specified: Silent mode" ;; V) verbosity=$inf_lvl edebug "-V specified: Verbose mode" ;; G) verbosity=$dbg_lvl edebug "-G specified: Debug mode" ;; esac done ewarn "this is a warning" eerror "this is an error" einfo "this is an information" edebug "debugging" ecrit "CRITICAL MESSAGE!" edumpvar ORACLE_SID |
Example:
1 |
$ example.sh -s |
1 |
$ example.sh |
1 |
$ example.sh -V |
1 |
$ example.sh -G |
It does not take into account the output file. That will be part of the next tip 🙂
Latest posts by Ludovico (see all)
- New views in Oracle Data Guard 23c - January 3, 2024
- New in Data Guard 21c and 23c: Automatic preparation of the primary - December 22, 2023
- Does FLASHBACK QUERY work across incarnations or after a Data Guard failover? - December 13, 2023
Thanks for tthis. I have used this heavily and made some modifications myself https://github.com/p1r473/zsh-color-logging take a look and tell me what you think!
Nice! which reminds me that I now have a Mac and I should give zsh a chance.
Pingback: Bash tips & tricks [ep. 4]: Use logging levels - Ludovico Caldara - Blogs - triBLOG