msgs.sh

Author Andy Smith
Compatibility Xymon 4.2,4.3
Requirements unix
Download None
Last Update 2014-08-29

This is a server-side extension that scans hosts.cfg for custom tags defining log files to be treated separately. Collection and analysis of the log files is carried out as per the msgs column described in the documentation, this extension merely reproduces the status log for the named log files under a different test name. This is useful if you need to configure different actions for alerts in different log files in the critical view.

Client side

N/A

Server side

Copy script to server/ext/ directory, create entry in tasks.cfg or new file in tasks.d/ directory.

Add tag with the following format to the hosts.cfg entry for desired logs on the relevant hosts:-

MSGS:/path/to/log/file:column_name

You must have previously configured the log /path/to/log/fileto be collected in client-local.cfg and it is expected that there will be a corresponding 'LOG' test configured in analysis.cfg

For troubleshooting, run with '-n' and/or '-x9'.

msgs.sh

Copy this to the “server/ext” directory on your Xymon server.

Show Code ⇲

Hide Code ⇱

#!/bin/sh
#ident  "@(#)msgs.sh 0.2.0"
#******************************************************************************
# $Id: msgs.sh 225 2014-08-29 14:28:47Z asmith69 $
# $Revision: 225 $
# $Author: asmith69 $
# $Date: 2014-08-29 15:28:47 +0100 (Fri, 29 Aug 2014) $
# $HeadURL: svn://galahad/xymon_addons/trunk/Extensions/msgs.sh $
#******************************************************************************
###############################################################################
# This code scans hosts.cfg for hosts marked with a 'msgs' test and for each
# of these, it will retrieve the relevant part of the current [msgs] log and
# create an alternate column for the given log file.
###############################################################################
#   0.0.0  a while ago   abs First version
#   0.1.0  2014-01-26    abs cleaned up and made portable
#   0.2.0  2014-08-29    abs send message via stdin to avoid command line
#                            length issues.
#                            add a blank line between all paragraphs to ensure
#                            only the correct parts of the original page are
#                            presented, also, discard the full log and cater
#                            for any markup conflicts.
###############################################################################
# embedded debug command ....
$DBG_SH
#Command=`basename $0 .sh`
Command=`basename $0`
Version=`sed '/^\#ident.*@(#).*$/!d; s/^\(#ident.*@(#)\)\([^    ]*\)\([         ]*\)\([^        ]*\)\([         ]*\)\([^        ]*\)\([         ]*\)\([^        ]*\)"$/\4/;q' $0`

whichunix(){
OSTYPE="unix"
case `uname -m` in
  sun4*)
    case `uname -r | cut -d. -f1` in
      4)      OSTYPE="sunos";;
      5)      OSTYPE="solaris";;
    esac ;;
  i86pc) OSTYPE="solaris" ;;
  i?86|x86_64)
    case `uname -r` in
      3.2) OSTYPE="sysv"
    esac
    case `uname -s` in
      Linux) OSTYPE="linux"
    esac ;;
  *)
    case `uname -s` in
      HP-UX) OSTYPE="hpux" ;;
      AIX) OSTYPE="aix" ;;
    esac ;;
  esac
  echo $OSTYPE
}
SED=/bin/sed
GREP=/bin/grep
EGREP=/bin/egrep
case `whichunix` in
  linux)
    ECHO="echo -e"
    AWK=/usr/bin/gawk
    PING=/bin/ping
    PINGOPTS=-nqc1
    ;;
  *)
    ECHO="echo"
    AWK=/usr/bin/nawk
    PING=/usr/sbin/ping
    PINGOPTS=-nc1
    ;;
esac
PING=portqry
PINGOPTS=
MyBadge="
$Command        version $Version        column"

# Correct command-line invocation usage ....
Usage="Usage:\t$Command [<options>] [<Value1....>]
\t-n\t\tDont send results to Xymon
\t-D <Server Name>\tReport specified Server Name(s)
\t-h\t\tThis Help"

###############################################################################
# de-bugging functions ....
show_only()   { echo "$*"; return $?; }
show_and_do() { echo "$*"; eval "$*"; return $?; }
do_only()     { eval "$*"; return $?; }
usage_exit()  { $ECHO $1 >&2; $ECHO "$Usage" >&2; exit 1; }
err_exit()    { $ECHO "$Command: $1" >&2; exit 1; }
###############################################################################
alarm() {
  perl -e 'alarm shift;
  exec @ARGV' "$@";
}
###############################################################################
portqry() {
  /opt/soe/local/bin/perl -e 'use Net::Ping;
  ($host, $port, $timeout) = @ARGV;
  $port = 22 if !$port;
  $timeout = 2 if !$timeout;
  $r = 1;
  $p = Net::Ping->new("tcp", $timeout);
  $p->port_number($port);
  $r = 0 if $p->ping($host);
  $p->close();
  exit($r);' "$@"
}
###############################################################################
nexpr() {
  $AWK '
    func min(m,n){return(m<n?m:n)};
    func max(m,n){return(m>n?m:n)};
    BEGIN { print '"$*"' ; exit }'
}
###############################################################################
epoch_ticks_to_human_readable() {
  perl -e "print scalar(gmtime($1/1000))"
}
###############################################################################
epoch_ticks() {
  perl -e "print time"
}
###############################################################################
send_status_to_xymon() {
# Create the status page
case $CurrentStatus in
  $GREEN) COLOR=green;;
  $YELLOW) COLOR=yellow;;
  $RED) COLOR=red;;
esac

End=`epoch_ticks`
Duration=`expr $End - $Begin`

# Send text status to xymon for display on the page, set the
# colour as appropriate.
echo "status ${MACHINE}.$COLUMN $COLOR `date`
$MSG
${MyBadge} $COLUMN tested in $Duration Seconds" | $XYMON $XYMSRV "@"
}
###############################################################################
send_data_to_xymon() {
  if [ -n "${DATA}" ]
  then
    # Send the CSV to xymon for capture by the rrd module
    $XYMON $XYMSRV "data ${MACHINE}.$COLUMN

${DATA}
"
  fi
}
###############################################################################
send_clear_status_to_xymon() {
# grab what was there before
ThePage=`$XYMONSTATUS $XYMSRV "xymondlog ${MACHINE}.$COLUMN" | \
  $SED -n '/<H2>/,$p' | \
  $SED -e 's/\&green/\&clear/;s/\&white/\&clear/;s/\&red/\&clear/;s/\&yellow/\&clear/'`

  # Send text status to xymon for display on the page, set the
  # colour as appropriate.

  echo "status ${MACHINE}.$COLUMN clear `date`
${TheError}
${ThePage}" | $XYMON $XYMSRV "@"
}
###############################################################################
Server_Summary() {
  # grab the full message log that Xymon already analysed
  # for all the defined msgs tests
  # make sure there is a blank line between all paragraphs
  MSGLOG=`$XYMONCOMMS $XYMSRV \
    "xymondlog ${MACHINE}.msgs" \
    | sed -n '2,$p' \
    | sed '/Full log\|\(Critical entries\|Warnings\|No entries\) in/{x;p;x;}' \
    `

  if [ $? -eq 0 ]
  then
    Status=`$ECHO "$MSGLOG" | egrep '(No entries|Warnings|Critical entries) in .*'"$LogPath"`
    case "$Status" in
      "")
        MyColour='&yellow';CurrentStatus=$WHITE
        Status="No analysis specified for $LogPath"
        ;;
      ?yellow?Warnings*) MyColour='&yellow';CurrentStatus=$YELLOW ;;
      ?red?Critical*) MyColour='&red';CurrentStatus=$RED ;;
      *) MyColour='&green';CurrentStatus=$GREEN ;;
    esac
    $Comment Status=$Status

    # cut out the paragraphs in the full message log that refer to the
    # analysis of this logfile only
    PLogPath=`$ECHO "$LogPath" | sed 's;\([[$/.]\);\\\\\1;g'`
    $Comment PLogPath=$PLogPath
    # the first sed will leave a leading blank line which needs to be trimmed
    # using the second sed.  Also, the warning case in analysis will insert
    # gratuitous <pre> and </pre> tags which need to be trimmed as well.
    Loglines=`$ECHO "$MSGLOG" | sed \
                                   -e '/./{H;$!d;}' \
                                   -e 'x;/\(Critical entries\|Warnings\|No entries\) in .*'$PLogPath'/!d;' \
                              | sed \
                                   -e '/^$/d' \
                                   -e '/<pre>/d' \
                                   -e '/<\/pre>/d' \
                              | sed \
                                   -e '/\(Critical entries\|Warnings\|No entries\) in .*'$PLogPath'/G' \
                                   -e '2,$s/</\&lt;/g' \
                                   -e '2,$s/>/\&gt;/g' \
                                   -e '2,$s/^\./\&#91;/' \
                                   -e '2,$s/^\(&\(yellow\|red\)\) \./\1 \&#91;/' \
                                   `
    # in the last sed, add a blank line after the heading anchor
    # and replace potential markup conflicts

    MSG="

$Loglines

"
    # just in case we forgot to analyse this logfile, it will get sent
    # back as a clear, so make the page useful
    TheError="$Status

$Loglines
"
  else
    MyColour='&red';CurrentStatus=$WHITE
    TheError="$XYMONCOMMS $XYMSRV 'xymondlog ${MACHINE}.msgs' sulked"
    MSG="`date`

$TheError
"
  fi

  return $CurrentStatus
}

###############################################################################

###############################################################################
XYMONHTAG=msgs                   # What we put in hosts.cfg to trigger this test
COLUMN=$XYMONHTAG                # Column name, often same as tag in hosts.cfg
XYMONVSN=4.3.12
###############################################################################
# inherit this from the environment or startup profile if its there
case $XYMONVSN in
  4.2*)
    XYMONCLIENTHOME="/usr/lib/xymon/client"
    XYMONSERVERHOME="/usr/lib/xymon/server"
    XYMONCOMMS=bb
    HOSTGREP=bbhostgrep
    ;;
  *)
    XYMONCLIENTHOME="/apps/xymon/client"
    XYMONSERVERHOME="/apps/xymon/server"
    XYMONCOMMS=xymon
    HOSTGREP=xymongrep
    ;;
esac
if [ -d $XYMONSERVERHOME ]
then
  if [ -z "$XYMONHOME" ]
  then
    XYMONHOME="$XYMONSERVERHOME" # Directory for the Xymon server files
  fi
else
  if [ -z "$XYMONHOME" ]
  then
    XYMONHOME="$XYMONCLIENTHOME" # Directory for the Xymon client files
  fi
fi
if [ -z "$XYMON" ]
then
  XYMON="$XYMONHOME/bin/${XYMONCOMMS}"   # The Xymon client "xymon" utility
fi
if [ -z "$XYMONTMP" ]
then
  XYMONTMP="$XYMONHOME/tmp"      # Where we may store temporary files.
fi
if [ -z "$XYMONVAR" ]
then
  XYMONVAR="$XYMONHOME/data"     # The directory holds all monitoring data
fi
if [ -z "$MACHINEDOTS" ]
then
  MACHINEDOTS="`uname -n`"
fi
XYMONGREP=$XYMONHOME/bin/${HOSTGREP}
XYMONSTATUS=$XYMONHOME/bin/${XYMONCOMMS}   # so we can query when debugging
[ -w $XYMONTMP ] || XYMONTMP="/tmp"
#

if [ -z "$XYMSRV" ]
then
  if [ -n "$BBDISP" ]
  then
    XYMSRV=$BBDISP
  else
    XYMSRV=127.0.0.1
  fi
fi
export XYMONHOME XYMON XYMONCOMMS XYMONTMP XYMONVAR XYMONDISP XYMSRV

# make somewhere for us to scribble
ScratchDir=${XYMONTMP}/${XYMONHTAG}_$$
TheOutput=$ScratchDir/status
mkdir -p $ScratchDir
trap "rm -rf $ScratchDir" 0 1 3 5

# check for command line switches ....
DeBug=
Comment=:
Action=do_only
while getopts X:D:I:nhx: flag
do
  case $flag in
    X) XYMSRV="$OPTARG" ;;
    D) TheServers="$OPTARG" ;;
    n) XYMON=echo ;;
    x) DeBug="-x $OPTARG"
      case ${OPTARG} in
        0) Action=do_only ;;
        1) Action=show_and_do ;;
        2) Action=show_and_do ;;
        3) Action=show_only; XYMON=echo ;;
        *) Action=show_only; XYMON=echo; Comment=echo ;;
      esac
      ;;
    h|\?) usage_exit "" ;;
  esac
done
shift `expr $OPTIND - 1`

# adjust path to be able to use xymon utils
PATH=$PATH:$XYMONHOME/bin; export PATH

[ $# -gt 0 ] && RuntimeValues="${@}"

# if not in the c/l, select each host in hosts.cfg with this test defined
if [ -z "$TheServers" ]
then
  TheServers=`$XYMONGREP "${XYMONHTAG}*" | $AWK '{print $2}'`
fi

# Lets go ....
RED=3;YELLOW=2;GREEN=1;WHITE=142
Start=`epoch_ticks`

for Server in $TheServers
do
  $Comment "analysing Server $Server"
  Begin=`epoch_ticks`
  MACHINE=`echo $Server | $SED -e's/\./,/g'`

  TheTags=`$XYMONCOMMS $XYMSRV "hostinfo host=$Server" | \
           tr '|' '\\n' | grep -i ${XYMONHTAG}:`

  $Comment "analysing hostinfo $TheTags"
  for Tag in $TheTags
  do
    $Comment "  analysing HOST TAG $Tag"
    # Re-initialise everything for this loop
    MSG=""; DATA=""; TheError=""; COLUMN=""

    # MSGS:/usr/lib64/xymon/client/tmp/error.log:msgs_error
    LogPath=`echo $Tag | awk -F: '{print $2}'`
    COLUMN=`echo $Tag | awk -F: '{print $3}'`
    [ -z "$COLUMN" ] && COLUMN=msgs_`basename $LogPath .log`

    $Comment "  LogPath=$LogPath"
    $Comment "  COLUMN=$COLUMN"
    CurrentStatus=$GREEN

    # Check that Server is accessible and create a summary page
    Server_Summary

    # send the update to Xymon
    [ $? -ne $WHITE ] && send_status_to_xymon || send_clear_status_to_xymon

  done # TheTags

done # TheServers

exit 0

tasks.d/msgs

Copy this to the “tasks.d” directory on your Xymon server.

Show Code ⇲

Hide Code ⇱

[msgs]
        #DISABLED
        ENVFILE /apps/xymon/server/etc/xymonserver.cfg
        CMD $XYMONHOME/ext/msgs.sh
        LOGFILE $XYMONSERVERLOGS/msgs.log
        INTERVAL 1m
  • 2014-01-26
    • Initial release
  • 2014-08-29
    • send message via stdin to avoid command line length issues.
    • add a blank line between all paragraphs to ensure only the correct parts of the original page are presented.
    • discard the full log and cater for any markup conflicts.
  • monitors/msgs.txt
  • Last modified: 2014/08/29 14:43
  • by shadymint