Add logging functionality to bash / shell scripts.

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;
fi

Specify 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)

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.

content of utils.sh:
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 Standard
if [ -z „${LOGLEVEL}“ ]; then
   LOGLEVEL=1;
fi
#Logdir nicht definiert
if [ -z „${LOGDIR}“ ]; then
   echo „WARN: LOGDIR nicht gesetzt! Ich nutze das Ausführungsverzeichnis $(pwd)/Log!“
   LOGDIR=“$(pwd)/Log“
fi
# If now Logfile defined, it will automatically set.
if [ -z „${LOGFILE}“ ]; then
   echo „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 Standard
if [ -z „${ENABLE_LOG}“ ]; then
   echo „ERROR: ENABLE_LOG nicht gesetzt! Wird deaktiviert!“
   ENABLE_LOG=0;
fi
LOGTYPE=$1
LOGLEVELID=$2
LOGMSG=$3
CSVLOG=“${LOGDIR}/run.csv“
if [ ! -d ${LOGDIR} ] ; then
   mkdir -p ${LOGDIR};
fi
## Map integer Loglevel to description
case „${LOGLEVELID}“ in
   DEBUG) LOGLID=0;;
    INFO) LOGLID=1;;
    WARN) LOGLID=2;;
   ERROR) LOGLID=3;;
esac
if [ ${DEBUG} -eq 1 ] ; then
     echodbg „DEBUG: $LOGMSG“
fi
## Prints only Messages based on LOGLEVEL and LOGTYPE
case „${LOGTYPE}“ in
   begin)
   if [ ${LOGLID} -ge ${LOGLEVEL} ]; then
   # Logfile or STDOUT
      if [ ${ENABLE_LOG} -eq 1 ] ;then
    echo „###################################################“ >>${LOGFILE}
         echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID}  ${LOGMSG}“ >>${LOGFILE}
      else
         echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID}  ${LOGMSG}“;
      fi
   fi
   ;;
   end)
   if [ ${LOGLID} -ge ${LOGLEVEL} ]; then
   # Logfile or STDOUT
      if [ ${ENABLE_LOG} -eq 1 ] ;then
    echo „—————————————————“ >>${LOGFILE}
         echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID}  ${LOGMSG}“ >>${LOGFILE}
      else
         echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID}  ${LOGMSG}“;
      fi
   fi
   ;;
   regular)
   # Logs by LOGLEVEL
   if [ ${LOGLID} -ge ${LOGLEVEL} ]; then
   # Logfile or STDOUT
      if [ ${ENABLE_LOG} -eq 1 ] ;then
         echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID}  ${LOGMSG}“ >>${LOGFILE}
      else
         echo „$(date +%Y_%m_%d-%H:%M:%S) ${LOGLEVELID}  ${LOGMSG}“;
      fi
   fi
   ;;
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;
fi

For 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“

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.