To debug or logging bash scripts may be simple with
echo „Text“ > logfile
I’m sure in most cases it will be managed like that. But how to diff between error debug and maybe warnings and handle it? Logging mechanism is so usefull, why not to use in shell scripts, too?
Add logging functionality in shell scripts
At first a a base functionality in bash shell scripts.
To include other scripts and maybe universal tools / functions and also keep main task and script simple and slime it may helpfull to outsource and organize this stuff to own scripts. In my own case i export universal solutions to a file, called: utils.sh.
To implement it, it’s neccessary to source this files. Can be done by:
if [ -f ./utils.sh ] ;then
. ./utils.sh
else
echo „ERROR: ./utils.sh not available“
exit 1;
fiSpecify the requirement of our Logging function
Configuration parameters
- Logfile Name and destination
- Loglevel, typically „DEBUG, INFO, WARN, ERROR“
- Specify Loglevel and Log higher classed Level.
- In DEBUG Level , INFO, WARN and ERROR should be also logged.
- In INFO Level, WARN and ERROR should be also logged, but now DEBUG messages.
- In WARN Level only WARN and ERROR.
- In ERROR Level just ERROR Messages wanted.
- Logtypes
- When using a logfile a day it may helpful to format the Start and End of a script.
- Start
- End
- regular (Just Print message out)
- Statistics for example duration of tasks. (well be integrated a other time
- Log to Logfile or Console (DEBUG Mode)
- When using a logfile a day it may helpful to format the Start and End of a script.
- Specify Loglevel and Log higher classed Level.
How to handle loglevels?
A mathematical rule is the simplest method of control.
So lets define numeric values for Loglevel
- DEBUG = 0
- INFO = 1
- WARN = 2
- ERROR = 3
This also follows typically settings maybe return codes in some cases.
function log() {###################################################### printlog <Logtype> <Loglevel> <Logmessage>## usage:## printlog <starttrans|stoptran|regular> <DEBUG|INFO|WARN|ERROR> <Message>## 0 = DEBUG## 1 = INFO## 2 = WARN## 3 = ERROR#Loglevel nicht definiert Loggen auf Standardif [ -z „${LOGLEVEL}“ ]; thenLOGLEVEL=1;fi#Logdir nicht definiertif [ -z „${LOGDIR}“ ]; thenecho „WARN: LOGDIR nicht gesetzt! Ich nutze das Ausführungsverzeichnis $(pwd)/Log!“LOGDIR=“$(pwd)/Log“fi
if [ -z „${LOGFILE}“ ]; thenecho „WARN: LOGFILE nicht gesetzt! Ich nutze das Ausführungsverzeichnis $(pwd)/Log/run.txt!“LOGFILE=“${LOGDIR}/logfile$(date +%Y-%m-%d ).log“fi#Loglevel nicht deifiniert Loggen auf Standardif [ -z „${ENABLE_LOG}“ ]; thenecho „ERROR: ENABLE_LOG nicht gesetzt! Wird deaktiviert!“ENABLE_LOG=0;fiLOGTYPE=$1LOGLEVELID=$2LOGMSG=$3CSVLOG=“${LOGDIR}/run.csv“if [ ! -d ${LOGDIR} ] ; thenmkdir -p ${LOGDIR};fi## Map integer Loglevel to descriptioncase „${LOGLEVELID}“ inDEBUG) LOGLID=0;;INFO) LOGLID=1;;WARN) LOGLID=2;;ERROR) LOGLID=3;;esacif [ ${DEBUG} -eq 1 ] ; thenechodbg „DEBUG: $LOGMSG“fi## Prints only Messages based on LOGLEVEL and LOGTYPEcase „${LOGTYPE}“ inbegin)if [ ${LOGLID} -ge ${LOGLEVEL} ]; then# Logfile or STDOUTif [ ${ENABLE_LOG} -eq 1 ] ;thenecho „###################################################“ >>${LOGFILE}echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID} ${LOGMSG}“ >>${LOGFILE}elseecho „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID} ${LOGMSG}“;fifi;;end)if [ ${LOGLID} -ge ${LOGLEVEL} ]; then# Logfile or STDOUTif [ ${ENABLE_LOG} -eq 1 ] ;thenecho „—————————————————“ >>${LOGFILE}echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID} ${LOGMSG}“ >>${LOGFILE}elseecho „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID} ${LOGMSG}“;fifi;;regular)# Logs by LOGLEVELif [ ${LOGLID} -ge ${LOGLEVEL} ]; then# Logfile or STDOUTif [ ${ENABLE_LOG} -eq 1 ] ;thenecho „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID} ${LOGMSG}“ >>${LOGFILE}elseecho „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID} ${LOGMSG}“;fifi;;esac}
How to use in in your script:
LOGLEVEL=“0″;
ENABLE_LOG=“1″;
#Rund in Logging / Debug Mode only, means to print out log messages to STDOUT
DEBUG=0;
LOGDIR=“$(pwd)/log“
LOGFILE=“$LOGDIR/$(date +%Y%m%d)_edf_globalextra.log“#then source the utils.sh
if [ -f ./utils.sh ] ;then
. ./utils.sh
else
echo „ERROR: ./utils.sh not available“
exit 1;
fiFor now it can be used like this:
log „regular“ „INFO“ „Script $0 starts now.“
log „regular“ „DEBUG“ „Debug information maybe to verify some variables“
log „regular“ „ERROR“ „Something went wrong“