Просмотр исходного кода

add more nagios-plugins i've written

Jon Schipp 10 лет назад
Родитель
Сommit
a7d1adb3dd
17 измененных файлов с 1320 добавлено и 216 удалено
  1. 274 0
      check_arista.py
  2. 28 0
      check_bhr_queue_size.sh
  3. 71 71
      check_bro.sh
  4. 60 60
      check_connections.sh
  5. 84 0
      check_crashplan.sh
  6. 10 10
      check_crashplan_backup.py
  7. 4 4
      check_file_growth.sh
  8. 83 0
      check_fs_write.sh
  9. 4 4
      check_load.sh
  10. 274 0
      check_ossec.py
  11. 8 8
      check_osx_temp.sh
  12. 96 0
      check_pid.sh
  13. 67 15
      check_rsyslog.sh
  14. 112 0
      check_sagan.sh
  15. 109 0
      check_status_code.sh
  16. 33 41
      check_traffic.sh
  17. 3 3
      check_volume.sh

+ 274 - 0
check_arista.py

@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+# Author: Jon Schipp <jonschipp@gmail.com, jschipp@illinois.edu>
+import sys
+import os
+import argparse
+import json
+import filecmp
+import time
+from jsonrpclib import Server
+
+# Nagios exit codes
+NAGIOS_OK       = 0
+NAGIOS_WARNING  = 1
+NAGIOS_CRITICAL = 2
+NAGIOS_UNKNOWN  = 3
+
+# Build accepted check type options for argparse
+status_checks=['protocol_status', 'interface_status', 'duplex_status', 'bandwidth_status']
+rate_checks=['input_rate', 'output_rate']
+other_checks=['dumbno', 'link_status', 'traffic_status']
+all_checks= status_checks + rate_checks + other_checks
+
+result = NAGIOS_OK
+
+# Create dictionaries to minimize code
+DIRECTION_MAP = {
+  'input_rate':  'inBitsRate',
+  'output_rate': 'outBitsRate',
+}
+
+INTERFACE_MAP = {
+  'input_rate':  '9/1-24',
+  'output_rate': '3/1-16',
+}
+
+STATUS_MAP = {
+  'interface_status': 'interfaceStatus',
+  'protocol_status':  'lineProtocolStatus',
+  'duplex_status':    'duplex',
+  'bandwidth_status': 'bandwidth',
+}
+
+STATUS_MSG = {
+  0:  'OK',
+  1:  'WARNING',
+  2:  'CRITICAL',
+  3:  'UNKNOWN',
+}
+
+def cred_usage():
+  doc = '''
+  Could not open file! Does it exist? Is it valid JSON?
+
+  A file containing the API credentials in JSON should be read in using ``-f <file>''
+  Its contents should be formatted like this:
+
+  {
+    "user":"aristauser",
+    "password":"asdfasdfasdfasdf"
+  }
+  '''[1:]
+  return doc
+
+def check_rate(switch, direction, interfaces, skip):
+    response = switch.runCmds( 1, ["show interfaces Ethernet" + interfaces] )
+    ifs = response[0]["interfaces"]
+    d={}
+    rc=[]
+    for p,info in ifs.items():
+      if p in skip:
+        continue
+      if info["description"] is None:
+        continue
+      rate = info["interfaceStatistics"].get(direction, 0)  / (1000**2)
+      d[p] = [rate, threshold(rate)]
+    for nic in d:
+      status=d[nic][1]
+      rc.append(status)
+      print "%s: %s Mbps: %.2f" % (STATUS_MSG[status], nic, d[nic][0])
+    return rc
+
+def check_status(switch, option, devices, skip):
+    status_type=option
+    crit_items=["connected", "up", "duplexFull", 10000000000]
+    response = switch.runCmds( 1, ["show interfaces"])
+    ifs = response[0]["interfaces"]
+    result = NAGIOS_OK
+    for p,info in ifs.items():
+      if p in skip:
+        continue
+      if status_type == "bandwidth":
+        bw=crit_items[-1]
+        if int(info[status_type]) < bw:
+          print "CRITICAL: %s Bandwidth: %dGbps" % (p, info[status_type] / (1000**3))
+          result = NAGIOS_CRITICAL
+          continue
+      if devices != "None":
+        if p in devices:
+          if info[status_type] not in crit_items:
+            result = NAGIOS_CRITICAL
+            print "CRITICAL: %s %s" % (p, info[status_type])
+            continue
+          else: print "SUCCESS: %s %s" % (p, info[status_type])
+      if devices == "None":
+        if info["description"] is None:
+          continue
+        if status_type not in info:
+          continue
+        if info[status_type] not in crit_items:
+          result = NAGIOS_CRITICAL
+          print "CRITICAL: %s  %s" % (p, info[status_type])
+    if result == 0: print "SUCCESS: %s check successful" % status_type
+    return result
+
+def check_traffic_status(switch, skip):
+    response = switch.runCmds( 1, ["show interfaces"])
+    ifs = response[0]["interfaces"]
+    result = 0
+    for p,info in ifs.items():
+      if p in skip:
+        continue
+      if info["description"] is None:
+        continue
+      if info["lineProtocolStatus"] == "notPresent":
+        continue
+      if info["interfaceStatus"] == "notconnect":
+        continue
+      in_traffic = info["interfaceStatistics"]["inPktsRate"]
+      out_traffic = info["interfaceStatistics"]["outPktsRate"]
+      if in_traffic == 0 and out_traffic == 0:
+        print "CRITICAL: %s In: %s Out: %s" % (p, in_traffic, out_traffic)
+        result=1
+    if result == 1:
+      return NAGIOS_CRITICAL
+    else:
+      print "SUCCESS: Traffic is being processed by all connected interfaces"
+      return NAGIOS_OK
+
+def check_dumbno(switch, skip):
+    path    = '/root/%s' % os.path.basename(sys.argv[0]) + '-dumbno.state'
+    current = path + '.current'
+    old     = path + '.old'
+    response = switch.runCmds( 1, ["enable", "show ip access-lists"] )
+    acl_lists = response[1]["aclList"]
+    rules=[]
+    for list in acl_lists:
+      name = list["name"]
+      if name in skip:
+        continue
+      for rule in list["sequence"]:
+        if "permit" in rule["text"]:
+          continue
+        line = name + " - " + rule["text"]
+        rules.append(line)
+    if os.path.isfile(current):
+      os.rename(current, old)
+    save_file(rules, current)
+    return compare_file(current, old)
+
+def check_link_status(switch, skip):
+    path    = '/root/%s' % os.path.basename(sys.argv[0]) + '-flap.state'
+    current = path + '.current'
+    old     = path + '.old'
+    key = "lastStatusChangeTimestamp"
+    response = switch.runCmds( 1, ["show interfaces"])
+    ifs = response[0]["interfaces"]
+    data=[]
+    for p,info in ifs.items():
+      if p in skip:
+        continue
+      if key not in info:
+        continue
+      print p, info[key]
+    if os.path.isfile(current):
+      os.rename(current, old)
+    save_file(data, current)
+    return compare_file(current, old)
+
+def compare_file(current, old):
+  if not os.path.isfile(current):
+    print "First run, waiting to create history"
+    return NAGIOS_UNKNOWN
+  if not os.path.isfile(old):
+    return NAGIOS_UNKNOWN
+  if filecmp.cmp(current, old):
+    print "CRITICAL: Entries haven't changed"
+    return NAGIOS_CRITICAL
+  print "SUCCESS: Entries rules have changed"
+  return NAGIOS_OK
+
+def save_file(data, path):
+  file = "\n".join(data)
+  try:
+    with open(path, 'w') as f:
+      f.write(file)
+  except IOError:
+    print "Unable to open file for writing"
+    exit(NAGIOS_UNKNOWN)
+
+def threshold(value):
+  if value >= crit:
+    return NAGIOS_CRITICAL
+  if value >= warn:
+    return NAGIOS_WARNING
+  return NAGIOS_OK
+
+def arguments():
+  global crit
+  global warn
+
+  parser = argparse.ArgumentParser(description='Check Arista stats')
+  parser.add_argument("-s", "--skip",     type=str, help="Items to skip from check")
+  parser.add_argument("-d", "--device",   type=str, help="Devices to check (def: all) (sep: ,) e.g. Ethernet1/1/3")
+  parser.add_argument("-T", "--type",     type=str, help="Type of check", choices=all_checks)
+  parser.add_argument("-H", "--host",     type=str, help="<host:port> e.g. arista.company.org:443", required=True)
+  parser.add_argument("-f", "--filename", type=str, help="Filename that contains API credentials", required=True)
+  parser.add_argument("-c", "--critical", type=int, help="Critical value in Mbps")
+  parser.add_argument("-w", "--warning",  type=int, help="Warning value in Mbps")
+  args = parser.parse_args()
+
+  option = args.type
+  host = args.host
+  filename = args.filename
+  crit = args.critical
+  warn = args.warning
+
+  if args.skip:
+    skip = args.skip.split(",")
+  else:
+    skip = "None"
+  if args.device:
+    devices = args.device.split(",")
+  else:
+    devices = "None"
+
+  return(option, host, filename, devices, skip)
+
+def get_creds(filename):
+  try:
+    with open(filename, 'r') as f:
+      creds = json.load(f)
+    return creds
+  except IOError:
+    print cred_usage()
+    exit(NAGIOS_UNKNOWN)
+
+def main():
+  option, host, filename, devices, skip = arguments()
+  creds = get_creds(filename)
+  user = creds["user"]
+  password  = creds["password"]
+
+  url    = 'https://' + user + ':' + password + host + '/command-api'
+  switch = Server(url)
+
+  if option == "dumbno":
+    exit(check_dumbno(switch, skip))
+  elif option == "traffic_status":
+    exit(check_traffic_status(switch, skip))
+  elif option == "link_status":
+    exit(check_link_status(switch, skip))
+  elif option in status_checks:
+    option  =  STATUS_MAP[option]
+    exit(check_status(switch, option, devices, skip))
+  elif option in rate_checks:
+    direction  =  DIRECTION_MAP[option]
+    interfaces =  INTERFACE_MAP[option]
+    exit(max(check_rate(switch, direction, interfaces, skip)))
+  else:
+    print "Invalid option"
+    exit(NAGIOS_UNKNOWN)
+
+if __name__ == "__main__":
+  main()

+ 28 - 0
check_bhr_queue_size.sh

@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+# Nagios plugin to check the BHR queue size
+
+# Nagios Exit Codes
+OK=0
+WARNING=1
+CRITICAL=2
+UNKNOWN=3
+
+# set default values for the thresholds
+WARN=10
+CRIT=50
+
+QDIR="/var/lib/bhrqueue"
+
+entries=$(find $QDIR -type f | fgrep -v .lck | wc -l)
+
+if [ $entries -gt $CRIT ]; then
+        echo "CRITICAL: $entries"
+        exit $CRITICAL;
+elif [ $entries -gt $WARN ]; then
+        echo "WARNING: $entries"
+        exit $WARNING;
+else
+        echo "OK: $entries"
+        exit $OK;
+fi

+ 71 - 71
check_bro.sh

@@ -34,9 +34,10 @@ BROCTL=/usr/local/bro/bin/broctl
 # Set this to the proper location if your installation differs
 MYRI_COUNTERS=/opt/snf/bin/myri_counters
 
-# Default location of capture_loss.log
+# Default location of logs
 # Set this to the proper location if your installation differs
 CAPTURE_LOG=/usr/local/bro/logs/current/capture_loss.log
+STATS_LOG=/usr/local/bro/logs/current/stats.log
 
 usage()
 {
@@ -45,25 +46,26 @@ cat <<EOF
 Check status of Bro and Bro workers.
 This script should be run on the Bro manager.
 
-Options:
-  -c <int>                Critical threshold as percent of packet loss
-  -f <path>               Set optional absolute path for broctl, myri_counters, or capture_loss.log (Use as first option)
-                          (def: $BROCTL,
-                          $MYRI_COUNTERS,
-                          $CAPTURE_LOG)
-  -i <node/worker>        Identifier for Bro instance(s). IP, FQDN, or name depending on the check. (sep:, )
-  -p <name>               Print the value of data from Bro e.g. Notice::suppressing or capture_filter
-  -T <type>               Check type, "status/loss/capture_loss/myricom/print"
-                          status - Check status of all Bro workers
-                          loss   - Average packet loss by name for a single-
-                            (\`\`-i nids01''), set (\`\`-i "nids01,nids02"), or all workers (\`\`-i all'').
-                          capture_loss - Checks for packet loss in capture_loss.log
-                          myricom - Average Myricom Sniffer driver packet loss by IP or FQDN for a single-
-                            (\`\`-i 192.168.1.1'') or set (\`\`-i "192.168.1.1,192.168.1.2") of Bro nodes
-                            Connects to nodes via SSH (pub-key auth). If username is not root use ``-u''.
-                          print   - Print Bro values
-  -u <user>               Username for the myricom check (def: root)
-  -w <int>                Warning threshold as percent of packet loss
+  Options:
+    -c <int>          Critical threshold as percent of packet loss
+    -f <path>         Set optional absolute path for broctl, myri_counters, or capture_loss.log
+                      Use \`\`-f'' as first option on command-line.
+                      (def: $BROCTL,
+                      $MYRI_COUNTERS,
+                      $CAPTURE_LOG)
+    -i <node/worker>  Identifier for Bro instance(s). IP, FQDN, or name depending on the check. (sep:, )
+    -p <name>         Print the value of data from Bro e.g. Notice::suppressing or capture_filter
+    -T <type>         Check type, "status/loss/capture_loss/myricom/print"
+                      status - Check status of all Bro workers
+                      loss   - Average packet loss by name for a single
+                       > (\`\`-i nids01''), set (\`\`-i "nids01,nids02"), or all workers (\`\`-i all'').
+                      capture_loss - Checks for packet loss in capture_loss.log
+                      myricom - Average Myricom Sniffer driver packet loss by IP or FQDN for a single-
+                       > (\`\`-i 192.168.1.1'') or set (\`\`-i "192.168.1.1,192.168.1.2") of Bro nodes
+                       > Connects to nodes via SSH (pub-key auth). If username is not root use ``-u''.
+                      print   - Print Bro values
+    -u <user>         Username for the myricom check (def: root)
+    -w <int>          Warning threshold as percent of packet loss
 
 Usage: $0 -f /usr/local/bro-dev/bin/brotcl -T status
 $0 -f /usr/local/bro-2.2/logs/current/capture_loss.log -T capture_loss -c 20
@@ -104,9 +106,7 @@ argcheck 1
 while getopts "hfc:i:lm:p:T:u:w:" OPTION
 do
   case $OPTION in
-    h)
-      usage
-      ;;
+    h) usage;;
     f)
       shift
       if [[ $1 == *broctl ]]; then
@@ -115,6 +115,9 @@ do
         MYRI_COUNTERS=$1
       elif [[ $1 == *capture_loss.log ]]; then
         CAPTURE_LOG=$1
+      # Custom thing written by jazoff - hopefully integrated into Bro upstream sometime
+      elif [[ $1 == *current/stats.log ]]; then
+        STATS_LOG=$1
       else
         echo "File name appears to be incorrect, maybe try setting the approprate variable in $0."
       fi
@@ -158,14 +161,14 @@ do
       fi
       ;;
     u)
-        USER="$OPTARG"
-        ;;
+      USER="$OPTARG"
+      ;;
     w)
-        WARN="$OPTARG"
-        ;;
+      WARN="$OPTARG"
+      ;;
     \?)
-        exit 1
-        ;;
+      exit 1
+      ;;
   esac
 done
 
@@ -184,9 +187,8 @@ fi
 
 if [ $LOSS_CHECK -eq 1 ]; then
 
-# Total average packet loss as a percent for specified workers
-FLOAT_LOSS=$($BROCTL netstats | grep "$WORKERS" | sed 's/[a-z]*=//g' | awk '{ drop += $4 ; link += $5 } END { printf("%f\n", ((drop/NR) / (link/NR))* 100) }')
-LOSS=$(/usr/bin/printf "%d\n" $FLOAT_LOSS 2>/dev/null)
+  FLOAT_LOSS=$($BROCTL netstats | grep "$WORKERS" | sed 's/[a-z]*=//g' | awk '{ drop += $4 ; link += $5 } END { printf("%f\n", ((drop/NR) / (link/NR))* 100) }')
+  LOSS=$(/usr/bin/printf "%d\n" $FLOAT_LOSS 2>/dev/null)
 
   if [ $LOSS -gt $CRIT ] ;then
     echo "Average packet loss is: $FLOAT_LOSS"
@@ -206,29 +208,28 @@ if [ $STATUS_CHECK -eq 1 ]; then
 
 # Broctl stderr is whitespace separated and we need to match on entire line
 IFS=$'\n'
-
-  for line in $($BROCTL status 2>&1 | grep -v 'Name\|waiting\|Getting')
-  do
-    NAME=$(echo "$line" | awk '{ print $1 }')
-    case "$line" in
-    *stop*)
-      echo "$NAME has stopped"
-      STOPPED=$((STOPPED+1))
-      ;;
-    *fail*)
-      echo "$NAME has crashed"
-      CRASHED=$((CRASHED+1))
-      ;;
-    *run*)
-      echo "$NAME is running"
-      RUNNING=$((RUNNING+1))
-      ;;
-    *)
-      echo "Unknown status of worker: $NAME"
-      UNKNOWN_WORKER=$((UNKNOWN_WORKER+1))
-      ;;
-    esac
-  done
+for line in $($BROCTL status 2>&1 | grep -v 'Name\|waiting')
+do
+  NAME=$(echo "$line" | awk '{ print $1 }')
+  case "$line" in
+  *stop*)
+    echo "$NAME has stopped"
+    STOPPED=$((STOPPED+1))
+    ;;
+  *fail*)
+    echo "$NAME has crashed"
+    CRASHED=$((CRASHED+1))
+    ;;
+  *run*)
+    echo "$NAME is running"
+    RUNNING=$((RUNNING+1))
+    ;;
+  *)
+    echo "Unknown status of worker: $NAME"
+    UNKNOWN_WORKER=$((UNKNOWN_WORKER+1))
+    ;;
+  esac
+done
 
   if [ $STOPPED -gt 0 ] || [ $CRASHED -gt 0 ] || [ $UNKNOWN_WORKER -gt 0 ]; then
     echo "-> $STOPPED stopped workers, $CRASHED crashed workers, $RUNNING running workers, and $UNKNOWN_WORKER workers with an unknown status"
@@ -250,24 +251,24 @@ if [ $CAPTURE_LOSS_CHECK -eq 1 ]; then
   RECENT=$(echo $((TIME-INTERVAL)))
 
   awk -v recent=$RECENT -v crit=$CRIT -v loss=0 -v threshold=0 '! /^#/ && $1 > recent && $4 > 0 \
-    {
-      loss++; decimal=sprintf("%d", $6);
-      if ( strtonum(decimal) > crit ) {
-        threshold++
-        print "Peer: "$3,"\t","Loss:", $6;
-      }
-    }
+     {
+            loss++; decimal=sprintf("%d", $6);
+            if ( strtonum(decimal) > crit ) {
+  		threshold++
+                    print "Peer: "$3,"\t","Loss:", $6;
+  	}
+     }
 
     END {
-      if ( loss >= 1 ) {
-        print "\n--------------------\n"loss,"instances of loss with",threshold,"exceeding the threshold ("crit"%).";
-        if ( threshold > 0 ) {
-          exit 2
-        }
-        exit 0
-      }
+  	 if ( loss >= 1 ) {
+                    print "\n--------------------\n"loss,"instances of loss with",threshold,"exceeding the threshold ("crit"%).";
+                    if ( threshold > 0 ) {
+                            exit 2
+                    }
+                    exit 0
+            }
     else
-      print "\nNo loss detected"; }' $CAPTURE_LOG
+             print "\nNo loss detected"; }' $CAPTURE_LOG
 
   if [ $? -eq 2 ]; then
     exit $CRITICAL
@@ -282,7 +283,6 @@ if [ $PRINT_CHECK -eq 1 ]; then
 fi
 
 if [ $MYRI_CHECK -eq 1 ]; then
-
 LOSS=0
 RECV=0
 COUNT=0

+ 60 - 60
check_connections.sh

@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-
+# Author: Jon Schipp <jonschipp@gmail.com, jschipp@illinois.edu>
 # Nagios Exit Codes
 OK=0
 WARNING=1
@@ -13,14 +13,14 @@ cat <<EOF
 Check the number of connections/sockets in a given state.
 Uses iproute2's ss tool to retrieve connections.
 
-     Options:
-        -s         State of connection (def: all)
-		   (established, syn-sent, syn-recv, fin-wait-1, fin-wait-2, time-wait,
-			closed, close-wait, last-ack, listen, and closing)
-	-f 	   Apply quoted ss expression filter e.g. '( dst 192.168.1/24 and dport >= :1024 )'
-	-p <type>  Set protocol or family type (udp/tcp/inet/inet6)
-        -c         Critical threshold as an integer
-        -w         Warning threshold as an integer
+  Options:
+    -s        State of connection (def: all)
+    	      (established, syn-sent, syn-recv, fin-wait-1, fin-wait-2, time-wait,
+    	           closed, close-wait, last-ack, listen, and closing)
+    -f 	      Apply quoted ss expression filter e.g. '( dst 192.168.1/24 and dport >= :1024 )'
+    -p <type> Set protocol or family type (udp/tcp/inet/inet6)
+    -c        Critical threshold as an integer
+    -w        Warning threshold as an integer
 
 Usage: $0 -s established '( sport = :443 )' -w 800 -c 1000
 EOF
@@ -29,14 +29,14 @@ EOF
 argcheck() {
 # if less than n argument
 if [ $ARGC -lt $1 ]; then
-        echo "Missing arguments! Use \`\`-h'' for help."
-        exit 1
+  echo "Missing arguments! Use \`\`-h'' for help."
+  exit 1
 fi
 }
 
 if ! command -v ss >/dev/null 2>&1; then
-	echo -e "ERROR: ss is not installed or not found in \$PATH!"
-	exit 1
+  echo -e "ERROR: ss is not installed or not found in \$PATH!"
+  exit 1
 fi
 
 # Define now to prevent expected number errors
@@ -47,60 +47,60 @@ COUNT=0
 ARGC=$#
 CHECK=0
 
-argcheck 1 
+argcheck 1
 
 while getopts "hc:s:f:p:w:" OPTION
 do
-     case $OPTION in
-         h)
-	     usage
-             ;;
-         s)
-             STATE="$OPTARG"
-	     CHECK=1
-             ;;
-         f)
- 	     FILTER="$OPTARG"
-	     CHECK=1
-             ;;
-	 p)
-	     if [[ $OPTARG == tcp ]]; then
-                PROTOCOL="-t"
-             elif [[ $OPTARG == udp ]]; then
-                PROTOCOL="-u"
-             elif [[ $OPTARG == inet ]]; then
-                PROTOCOL="-4"
-             elif [[ $OPTARG == inet6 ]]; then
-                PROTOCOL="-6"
-             else
-                echo "Error: Protocol or family type no valid!"
-		exit 1
-             fi
-	     CHECK=1
-	     ;; 
-         c)
-	     CRIT="$OPTARG"
-	     CHECK=1
-             ;;
-	 w) 
-	     WARN="$OPTARG"
-	     CHECK=1
-	     ;;
-         \?)
-             exit 1
-             ;;
-     esac
+  case $OPTION in
+    h)
+      usage
+      ;;
+    s)
+      STATE="$OPTARG"
+      CHECK=1
+      ;;
+    f)
+      FILTER="$OPTARG"
+      CHECK=1
+      ;;
+    p)
+      if [[ $OPTARG == tcp ]]; then
+        PROTOCOL="-t"
+      elif [[ $OPTARG == udp ]]; then
+        PROTOCOL="-u"
+      elif [[ $OPTARG == inet ]]; then
+        PROTOCOL="-4"
+      elif [[ $OPTARG == inet6 ]]; then
+        PROTOCOL="-6"
+      else
+        echo "Error: Protocol or family type no valid!"
+      exit 1
+      fi
+      CHECK=1
+      ;;
+    c)
+      CRIT="$OPTARG"
+      CHECK=1
+      ;;
+    w)
+      WARN="$OPTARG"
+      CHECK=1
+      ;;
+    \?)
+      exit 1
+      ;;
+  esac
 done
 
 COUNT=$(ss -n state $STATE $PROTOCOL $FILTER | grep -v 'State\|-Q' | wc -l)
 
 if [ $COUNT -gt $CRIT ]; then
-        echo "$COUNT sockets in $STATE state!"
-        exit $CRITICAL
+  echo "$COUNT sockets in $STATE state!"
+  exit $CRITICAL
 elif [ $COUNT -gt $WARN ]; then
-        echo "$COUNT sockets in $STATE state!"
-        exit $WARNING
+  echo "$COUNT sockets in $STATE state!"
+  exit $WARNING
 else
-        echo "$COUNT sockets in $STATE state."
-        exit $OK
-fi 
+  echo "$COUNT sockets in $STATE state."
+  exit $OK
+fi

+ 84 - 0
check_crashplan.sh

@@ -0,0 +1,84 @@
+#!/usr/bin/env bash
+
+# Author: Jon Schipp
+
+########
+# Examples:
+
+# 1.) Check if Crashplan is installed
+# $ ./check_crashplan.sh -I
+
+# 2.) Check Java heap settings of crashplan
+# $ ./check_crashplan.sh -H
+
+# Nagios Exit Codes
+OK=0
+WARNING=1
+CRITICAL=2
+UNKNOWN=3
+
+# Default Location of the binaries
+# Set these to the proper location if your installation differs
+CP_BIN=/usr/local/crashplan/bin/CrashPlanEngine
+CP_CONF=/usr/local/crashplan/bin/run.conf
+
+usage()
+{
+cat <<EOF
+
+Check status of CrashPlan on GNU/Linux
+
+     Options:
+        -I              Check if Crashplan is installed and running
+        -H              Check if Crashplan heap size is >= Xmx4096m
+
+Usage: $0 -H
+EOF
+}
+
+argcheck() {
+# if less than n argument
+if [ $ARGC -lt $1 ]; then
+        echo "Missing arguments! Use \`\`-h'' for help."
+        exit 1
+fi
+}
+
+# Initialize variables
+CHECK_INSTALLED=0
+CHECK_CONF=0
+ARGC=$#
+
+argcheck 1
+
+while getopts "hIH" OPTION
+do
+     case $OPTION in
+         h)
+             usage
+             ;;
+         I)
+             CHECK_INSTALLED=1
+             ;;
+         H)
+             CHECK_CONF=1
+             ;;
+         \?)
+             exit 1
+             ;;
+     esac
+done
+
+if [[ $CHECK_INSTALLED -eq 1 ]]; then
+  [[ -x $CP_BIN ]] || { echo "$CP_BIN not installed or executable" && exit $OK; }
+  status=$(service crashplan status 2>&1)
+  echo $status | egrep -q 'running|started' || { echo "$CP_BIN is installed but not running: ${status}" && exit $CRITICAL; }
+  echo "$CP_BIN is installed and running" && exit $OK
+fi
+
+if [[ $CHECK_CONF -eq 1 ]]; then
+  [[ -r $CP_CONF ]] || { echo "$CP_CONF not found or readable" && exit $OK; }
+  . $CP_CONF
+  echo $SRV_JAVA_OPTS | grep -q "Xmx[4-9][0-9][0-9][0-9][mM]" || { echo "Java heap too small: $SRV_JAVA_OPTS" && exit $CRITICAL; }
+  echo "Heap is okay" && exit $OK
+fi

+ 10 - 10
check_crashplan_backup.py

@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# Author: Jon Schipp <jonschipp@gmail.com, jschipp@illinois.edu>
 import sys
 import datetime
 import requests
@@ -12,7 +13,6 @@ nagios_warning  = 1
 nagios_critical = 2
 nagios_unknown  = 3
 
-import argparse
 parser = argparse.ArgumentParser(description='Last Crashplan backup check')
 parser.add_argument("-s", "--skip", type=str, help="Hosts to skip from backup check")
 parser.add_argument("-d", "--device", type=str, help="Specify deviceName to check (def: all)")
@@ -38,12 +38,12 @@ else:
 
 # Open file
 try:
-  f = open(filename, "r")
-  global data
-  creds = imp.load_source('data', '', f)
-  f.close()
+  with open(filename, 'r') as f:
+    creds = json.load(f)
+  user = creds["user"]
+  password = creds["password"]
 except IOError:
-  print "Could not open file! Does it exist?"
+  print "Could not open file! Does it exist? Is it valid JSON?"
   exit(nagios_unknown)
 
 def backup_check(device, orig_time):
@@ -51,7 +51,7 @@ def backup_check(device, orig_time):
   if time < critical_days:
     print "CRITICAL: %s: LastCompleteBackup: %s" % (device, orig_time)
     status = nagios_critical
-    
+
 def format_time(entry, orig_time):
   global time
   time = datetime.datetime.strptime(orig_time, "%b %d, %Y %I:%M:%S %p")
@@ -76,7 +76,7 @@ def check_host_backup():
       backup_check(device, orig_time)
 
 # Make API request
-r = requests.get(url, auth=(creds.user, creds.password))
+r = requests.get(url, auth=(user, password))
 r.raise_for_status()
 
 data  = r.json()
@@ -87,8 +87,8 @@ if host == 0:
 else:
  check_host_backup()
 
-if status == nagios_critical: 
+if status == nagios_critical:
   exit(nagios_critical)
 else:
-  print "OK: All backups have been completed recently" 
+  print "OK: All backups have been completed recently"
   exit(nagios_ok)

+ 4 - 4
check_file_growth.sh

@@ -79,7 +79,7 @@ PROG=wc
 OS=$(uname)
 ARGC=$#
 
-argcheck 4 
+argcheck 4
 
 while getopts "hc:f:i:M:T:w:" OPTION
 do
@@ -90,7 +90,7 @@ do
     CRIT="$OPTARG";;
   f)
     FILE="$OPTARG";;
-  i) 
+  i)
     TIME="$OPTARG";;
   M)
     PROG="$OPTARG"
@@ -113,7 +113,7 @@ do
     	echo "Unknown type!"
     	exit 1
     fi;;
-  w) 
+  w)
       WARN="$OPTARG";;
   \?)
       exit 1;;
@@ -142,7 +142,7 @@ fi
 
 GROWTH=$(($NEW-$OLD))
 
-if [[ $CONCERN -eq 0 ]]; then 
+if [[ $CONCERN -eq 0 ]]; then
   if [[ $GROWTH -gt 0 ]]; then
     echo "File grew by $GROWTH bytes"
     exit $OK

+ 83 - 0
check_fs_write.sh

@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+
+# Author: Jon Schipp
+# Date: 09-10-2014
+########
+# Examples:
+
+# 1.) Check if sshd has restarted since last check
+# $ ./check_fs_write.sh -o /var,/tmp
+
+# Nagios Exit Codes
+OK=0
+WARNING=1
+CRITICAL=2
+UNKNOWN=3
+
+usage()
+{
+cat <<EOF
+
+Notify if a filesystem is read-only by writing a file to it.
+
+     Options:
+        -f           Specify custom filename (optional)
+	-o	     Specify destinations to write, comma separated
+
+Usage: $0 -o /var,/home,/tmp,/nfs
+EOF
+}
+
+if [ $# -lt 1 ];
+then
+	usage
+	exit 1
+fi
+
+# Define now to prevent expected number errors
+CHECK=0
+CRIT=0
+FILE=68b329da9893e34099c7d8ad5cb9c940
+
+while getopts "hf:o:" OPTION
+do
+     case $OPTION in
+         h)
+	     usage
+             ;;
+	 f)
+	     FILE="$OPTARG"
+	     ;;
+	 o)
+	     DIR=$(echo "$OPTARG" | sed 's/,/ /g');
+	     CHECK=1
+	     ;;
+         \?)
+             exit 1
+             ;;
+     esac
+done
+
+if [ $CHECK -eq 1 ]; then
+
+	for directory in $DIR
+	do
+		timeout 3s touch $directory/$FILE 2>/dev/null
+		if [ $? -ne 0 ]; then
+			echo "Failure to write file to ${directory}!"
+			CRIT=1
+		else
+			rm -f $directory/$FILE
+			echo "Success writing file to $directory"
+		fi
+	done
+
+	if [ $CRIT -eq 1 ]; then
+		echo "State: CRITICAL"
+		exit $CRITICAL
+	else
+		echo "State: OK"
+		exit $OK
+	fi
+
+fi

+ 4 - 4
check_load.sh

@@ -69,7 +69,7 @@ elif [[ "$OS" == freebsd ]]; then
 	UPTIME=$(uptime | awk -F : '{ print $4 }' | sed 's/,//g')
 elif [[ "$OS" == aix ]]; then
 	UPTIME=$(uptime | awk -F : '{ print $4 }' | sed 's/,//g')
-else 
+else
 	echo "OS not supported"
 	exit $UNKNOWN
 fi
@@ -89,7 +89,7 @@ UNAME=$(uname)
  else
         echo "Unsupported OS type!"
         exit 1
- fi  
+ fi
 
 }
 
@@ -171,7 +171,7 @@ if [ $THRESHOLD -eq 1 ]; then
 			WARN_STATUS=$((WARN_STATUS+1))
 		else
 			OK_STATUS=$((OK_STATUS+1))
-		fi	
+		fi
 	done
 fi
 
@@ -181,7 +181,7 @@ if [ $CRIT_STATUS -gt 0 ]; then
 elif [ $WARN_STATUS -gt 0 ]; then
 	echo "Load average warning: $UPTIME"
 	exit $WARNING
-else 
+else
 	echo "Load average: $UPTIME"
 	exit $OK
 fi

+ 274 - 0
check_ossec.py

@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+# Author: Jon Schipp <jschipp@illinois.edu, jonschipp@gmail.com>
+
+# 1.) Check that all OSSEC services are running
+# $ ./check_ossec.py -T status
+
+# 2.) Check status of all OSSEC agents except one
+# $ ./check_ossec.py -T connected --skip www2.company.com
+
+# 3.) Check status of specific OSSEC agents
+# $ ./check_ossec.py -T connected --agents www1.company.com,www2.company.com
+
+# 4.) Report critical if more than 3 agents are offline and warning if at least 1 is offline.
+# $ ./check_ossec.py -T connected -c 3 -w 1
+
+# 5.) Check that a syscheck scan as completed for all agents in the last 12 hours, warning if 6
+# $ ./check_ossec.py -T syscheck -c 12 -w 6
+
+# 6.) Check that a rootcheck scan as completed for agent in the last 4 hours, warning if 2
+# $ ./check_ossec.py -T rootcheck --agents www2.company.com -c 4 -w 2
+
+import sys
+import argparse
+import os
+import subprocess
+import datetime
+import time
+
+# Nagios exit codes
+NAGIOS_OK       = 0
+NAGIOS_WARNING  = 1
+NAGIOS_CRITICAL = 2
+NAGIOS_UNKNOWN  = 3
+
+STATUS_MSG = {
+  0:  'OK',
+  1:  'WARNING',
+  2:  'CRITICAL',
+  3:  'UNKNOWN',
+}
+
+status_checks=['connected', 'syscheck', 'rootcheck', 'status']
+
+def arguments():
+  global path
+  # Defaults
+  crit = 1
+  warn = 1
+  path = '/var/ossec'
+
+  parser = argparse.ArgumentParser(description='Check OSSEC Configuration')
+  parser.add_argument("-s", "--skip",     type=str, help="Items to skip from check")
+  parser.add_argument("-a", "--agents",   type=str, help="Check status of agents (def: all) (sep:,) e.g. www1,www2")
+  parser.add_argument("-T", "--type",     type=str, help="Type of check", choices=status_checks)
+  parser.add_argument("-p", "--path",     type=str, help="Path of OSSEC directory (def: /var/ossec)")
+  parser.add_argument("-c", "--critical", type=int, help="Critical value in count for checks")
+  parser.add_argument("-w", "--warning",  type=int, help="Warning value in count for checks")
+  args = parser.parse_args()
+
+  option = args.type
+  if args.critical:
+    crit = args.critical
+  if args.warning:
+    warn = args.warning
+
+  if args.skip:
+    skip = args.skip.split(",")
+  else:
+    skip = "None"
+  if args.agents:
+    agents = args.agents.split(",")
+  else:
+    agents = False
+  if args.path:
+    path = args.path
+
+  return option, agents, skip, crit, warn
+
+def threshold(inactive_agents, crit, warn):
+  if inactive_agents >= crit:
+    return NAGIOS_CRITICAL
+  if inactive_agents >= warn:
+    return NAGIOS_WARNING
+  return NAGIOS_OK
+
+def is_ossec(path):
+ if os.path.isdir(path):
+   files = [
+     'etc/ossec.conf',
+     'etc/shared/agent.conf',
+     'bin/syscheck_control',
+     'bin/rootcheck_control',
+     'bin/agent_control'
+    ]
+   for f in files:
+     fp = path + '/' + f
+     if not os.path.isfile(fp):
+       print "Error: Installation missing file %s" % fp
+       return False
+ return True
+
+def get_output_dict(cmd, arg):
+  c=0
+  data={}
+  command = path + '/' + cmd
+  result = subprocess.Popen([command,arg],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+  set_result = set(result.stdout)
+  for i in set_result:
+    data[c]= [i.split(',')]
+    c += 1
+  return data
+
+def get_output_set(cmd, arg):
+  command = path + '/' + cmd
+  result = subprocess.Popen([command,arg],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+  data = set(result.stdout)
+  return data
+
+def is_server():
+  filename = '/etc/ossec-init.conf'
+  try:
+    with open(filename, 'r') as f:
+      contents = f.readlines()
+      install_type = contents[3].strip().split('=')[1]
+    if install_type == '"server"':
+      return True
+    else:
+      print "ERROR: Unable to detect OSSEC server: %s" % install_type
+      return False
+
+  except IOError:
+    print "ERROR: Cannot open file %s. Is OSSEC installed?" % filename
+    exit(NAGIOS_UNKNOWN)
+
+def open_queue(filename, service):
+  try:
+    with open(filename, 'r') as f:
+      for i in f.readlines():
+        if service == 'syscheck':
+          if 'Starting syscheck scan.' in i:
+            syscheck_start_ts = i[1:11]
+            return syscheck_start_ts
+        if service == 'rootcheck':
+          if 'Starting rootcheck scan.' in i:
+            rootcheck_start_ts = i[1:11]
+            return rootcheck_start_ts
+      else:
+            return False
+  except IOError:
+    print "ERROR: Cannot read queue file %s" % filename
+    exit(NAGIOS_UNKNOWN)
+
+def older_than(ts, name, crit_ts, warn_ts):
+  if not ts:
+      print "%s: %s: LastCheckTime: Unknown" % (STATUS_MSG[NAGIOS_UNKNOWN], name)
+      return NAGIOS_UNKNOWN
+  service_timestamp = datetime.datetime.fromtimestamp(float(ts))
+  if service_timestamp < crit_ts:
+      print "%s: %s: LastCheckTime: %s" % (STATUS_MSG[NAGIOS_CRITICAL], name, service_timestamp)
+      return NAGIOS_CRITICAL
+  elif service_timestamp < warn_ts:
+          print "%s: %s: LastCheckTime: %s" % (STATUS_MSG[NAGIOS_WARNING], name, service_timestamp)
+          return NAGIOS_WARNING
+  else:
+          return NAGIOS_OK
+
+def check_connected(agents, skip, crit, warn):
+  data = get_output_dict('bin/agent_control', '-l')
+  c=0
+  inactive_agents = 0
+  active = [ 'Active', 'Active/Local' ]
+  notactive = {}
+
+  for i in data:
+    line =  data[c][0]
+    c += 1
+    # Check for lines with fields we need
+    # Extract agent name and status message
+    if len(line) == 4:
+      name=line[1][6:].lstrip()
+      status=line[3].lstrip().rstrip()
+
+      # If --agents is specified only check for specified agents
+      if agents:
+        if name not in agents:
+          continue
+      else:
+        # If --agents is not specified check all except in skip
+        if name in skip:
+          continue
+
+      if status not in active:
+        notactive[name] = status
+        inactive_agents += 1
+
+  # Check if inactive agents were fonud
+  if notactive:
+    exit_code = threshold(inactive_agents, crit, warn)
+    print "%s: %d agents not connected" % (STATUS_MSG[exit_code], len(notactive))
+    for k,v in notactive.items():
+      print "Name: %s, Status: %s" % (k,v)
+    return exit_code
+  else:
+    print "%s: All agents connected" % STATUS_MSG[NAGIOS_OK]
+    return NAGIOS_OK
+
+def check_service(service, agents, skip, crit, warn):
+  dir = os.path.join(path,'queue/rootcheck')
+  crit_ts = datetime.datetime.now() - datetime.timedelta(hours=crit)
+  warn_ts = datetime.datetime.now() - datetime.timedelta(hours=warn)
+  status_list = []
+  for queue in os.listdir(dir):
+     name = queue.strip('()').split()[0].rstrip(')')
+     if agents:
+       if name not in agents:
+         continue
+     else:
+       if name == 'rootcheck':
+         continue
+       if name in skip:
+         continue
+     f = os.path.join(dir, queue)
+     if os.path.isfile(f):
+       ts = open_queue(f, service)
+       status = older_than(ts, name, crit_ts, warn_ts)
+     status_list.append(status)
+     exit_code = max(status_list)
+  if exit_code == NAGIOS_OK:
+    print "%s: Agent %s runtimes are up to date" % (STATUS_MSG[NAGIOS_OK],service)
+  return exit_code
+
+def check_status(agents, skip):
+  data = get_output_set('bin/ossec-control', 'status')
+  not_running=[]
+  for i in data:
+    # If --skip is used skip these
+    if i in skip:
+      continue
+    # Add names of services not running to list
+    if 'not running' in i:
+      not_running.append(i)
+      continue
+  # Test for entries in list. Entries mean something wasn't running
+  if not_running:
+    print "%s: Some services running" % STATUS_MSG[NAGIOS_CRITICAL]
+    for i in not_running:
+      print i.rstrip()
+    return NAGIOS_CRITICAL
+  else:
+    print "%s: All services running" % STATUS_MSG[NAGIOS_OK]
+    return NAGIOS_OK
+
+def main():
+  option, agents, skip, crit, warn = arguments()
+
+  if not is_ossec(path):
+    exit(NAGIOS_UNKNOWN)
+  if not is_server():
+    exit(NAGIOS_UNKNOWN)
+
+  if option == "connected":
+    exit(check_connected(agents, skip, crit, warn))
+  elif option == "syscheck":
+    exit(check_service(option, agents, skip, crit, warn))
+  elif option == "rootcheck":
+    exit(check_service(option, agents, skip, crit, warn))
+  elif option == "status":
+    exit(check_status(agents, skip))
+  else:
+    print "Invalid type option"
+    exit(NAGIOS_UNKNOWN)
+
+if __name__ == "__main__":
+  main()

+ 8 - 8
check_osx_temp.sh

@@ -50,13 +50,13 @@ do
          h)
 	     usage
              ;;
-	 t) 
+	 t)
 	     MONITOR=1
 	     ;;
-	 c) 
+	 c)
 	     CRIT="$OPTARG"
 	     ;;
-	 w) 
+	 w)
 	     WARN="$OPTARG"
 	     ;;
          \?)
@@ -68,11 +68,11 @@ done
 if [ $MONITOR -eq 1 ]; then
 	$COMMAND | sed 's/ F//' | awk -v crit=$CRIT -F : \
 	'$2 > crit { high=1; print $0 }
-	END { 
-	if (high == 1) { 
-		exit 2 
-	} else { 
-		exit 0 
+	END {
+	if (high == 1) {
+		exit 2
+	} else {
+		exit 0
 		}
 	}'
 

+ 96 - 0
check_pid.sh

@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+
+# Author: Jon Schipp
+# Date: 04-15-2014
+########
+# Examples:
+
+# 1.) Check if sshd has restarted since last check
+# $ ./check_pid.sh -f /var/run/sshd.pid
+
+# Nagios Exit Codes
+OK=0
+WARNING=1
+CRITICAL=2
+UNKNOWN=3
+
+usage()
+{
+cat <<EOF
+
+Check if a service has been restarted by comparing its PID to each previous run.
+
+  Options:
+    -f       Specify PID filename as full path
+    -o	     Temporary PID file storage directory (def: /tmp)
+
+Usage: $0 -f /var/run/sshd.pid -o /tmp/pids/
+EOF
+}
+
+if [ $# -lt 1 ];
+then
+  usage
+  exit 1
+fi
+
+# Define now to prevent expected number errors
+DIR=/tmp
+CHECK=0
+COUNT=0
+
+while getopts "hf:o:" OPTION
+do
+  case $OPTION in
+    h)
+      usage
+      ;;
+    f)
+      FILEPATH="$OPTARG"
+      CHECK=1
+      ;;
+    o)
+      DIR="$OPTARG"
+      ;;
+    \?)
+      exit 1
+      ;;
+  esac
+done
+
+FILE=$(echo $FILEPATH | sed 's/^.*\///')
+
+if [ ! -f $FILEPATH ]; then
+  echo "File doesn't exist or is not a regular file!"
+  exit $UNKNOWN
+fi
+
+if [ $CHECK -eq 1 ]; then
+  if [ ! -f $DIR/$FILE ]; then
+    echo "First run for PID or can't access file in temporary storage location: $DIR/$FILE"
+    cp -f $FILEPATH $DIR
+    exit $UNKNOWN
+  fi
+
+  # In case the PID is temporarily locked by another program
+  until [ ! -z $NEWPID ] && [ ! -z $OLDPID ];
+  do
+    NEWPID=$(cat $FILEPATH)
+    OLDPID=$(cat $DIR/$FILE)
+    COUNT=$((COUNT+1))
+    if [ $COUNT -ge 10 ]
+    then
+            break
+    fi
+  done
+
+  if [ $NEWPID -eq $OLDPID ]; then
+    echo "Service is still running with the same PID: $(echo $NEWPID)"
+    cp -f $FILEPATH $DIR
+    exit $OK
+  else
+    echo "Service restarted. OLDPID: $(echo $OLDPID) NEWPID: $(echo $NEWPID)"
+    cp -f $FILEPATH $DIR
+    exit $CRITICAL
+  fi
+fi

+ 67 - 15
check_rsyslog.sh

@@ -1,12 +1,15 @@
 #!/usr/bin/env bash
-
+# awk '{ for( i=NF; i>=1; i--) print $i }'
 # Author: Jon Schipp
 # Date: 01-27-2014
 ########
 # Examples:
 
 # 1.) Check presence of disk queue (buffer)
-# $ ./check_rsyslog.sh -q rsyslog -d /var/spool/rsyslog
+# $ ./check_rsyslog.sh -T buffer -q rsyslog -d /var/spool/rsyslog
+
+# 1.) Check number of logs currently in the queue
+# $ ./check_rsyslog.sh -T queued -f /var/log/impstats.log -c 100
 
 # Nagios Exit Codes
 OK=0
@@ -14,7 +17,7 @@ WARNING=1
 CRITICAL=2
 UNKNOWN=3
 
-# Default rsyslog spool directory 
+# Default rsyslog spool directory
 WORK_DIRECTORY=/var/spool/rsyslog
 
 usage()
@@ -22,13 +25,33 @@ usage()
 cat <<EOF
 
      Options:
-        -q <basename>    Check for presence of disk queue files
-	-d <dir>	 Specify \$WorkDirectory (def: /var/spool/rsyslog)
+	-c <int>	 Critical number
+	-w <int>	 Warning number
+        -q <basename>    Check for presence of disk queue files (use with \`\`-T buffer'')
+	-d <dir>	 Specify \$WorkDirectory (def: /var/spool/rsyslog) (use with \`\`-T buffer)
+	-f <file>	 Set file when using impstats checks
+	-T <type>	 Check type (buffer/queued)
+				buffer - Check for presence of buffer files
+				queued - Check impstats log file for number of queued logs
 
-Usage: $0 -q buf
+Usage: $0 -S buffer -q buf
 EOF
 }
 
+compare () {
+COUNT=$1
+if [ $COUNT -gt $CRIT ]; then
+        echo "CRITICAL: $BASENAME: $COUNT queued messages"
+        exit $CRITICAL;
+elif [ $COUNT -gt $WARN ]; then
+        echo "WARNING: $BASENAME: $COUNT queued messages"
+        exit $WARNING;
+else
+        echo "OK: $BASENAME: $COUNT queued messages"
+        exit $OK;
+fi
+}
+
 argcheck() {
 # if less than n argument
 if [ $ARGC -lt $1 ]; then
@@ -40,25 +63,46 @@ fi
 # Initialize variables
 ARGC=$#
 QUEUE_CHECK=0
+QUEUED_STATS_CHECK=0
+FILE=0
+CRIT=0
+WARN=0
 
 argcheck 1
 
-while getopts "hd:q:" OPTION
+while getopts "hc:w:f:d:q:T:" OPTION
 do
      case $OPTION in
-         h)
-             usage
-             ;;
+         h) usage ;;
+	 c) CRIT=$OPTARG ;;
+	 w) WARN=$OPTARG ;;
 	 d)
 	     WORK_DIRECTORY=$(echo $OPTARG | sed 's/\/$//')
 	     ;;
+         f)
+	     if [ -f $OPTARG ]; then
+	     	FILENAME="$OPTARG"
+		FILE=1
+	     else
+		echo "Does $OPTARG exist and is a regular file?"
+		exit $WARNING
+	     fi
+	     ;;
          q)
              BASENAME=$OPTARG
-	     QUEUE_CHECK=1
              ;;
+	 T)
+             if [[ "$OPTARG" == "queued" ]]; then
+                        QUEUED_STATS_CHECK=1
+	     elif [[ "$OPTARG" == "buffer" ]]; then
+			QUEUE_CHECK=1
+	     else
+			echo "$OPTARG is not a valid check type"
+			exit $WARNING
+	     fi
+	     ;;
          \?)
-             exit 1
-             ;;
+             exit $WARNING ;;
      esac
 done
 
@@ -67,14 +111,22 @@ if [ $QUEUE_CHECK -eq 1 ]; then
 	# Remove stale 0 byte queue files
 	# find $WORK_DIRECTORY -type f -size 0c -regextype posix-basic -regex ".*/$BASENAME.*\.[0-9]\{8\}" | xargs rm -rf
 
-	COUNT=$(find $WORK_DIRECTORY -type f -size +0c -regextype posix-basic -regex ".*/$BASENAME.*\.[0-9]\{8\}" | wc -l)
+	COUNT=$(find $WORK_DIRECTORY -type f -size +0c -regextype posix-basic -regex ".*/$BASENAME.*\.[0-9]\{7\}[2-9]" | wc -l)
 
 	if [ $COUNT -gt 0 ]; then
 		echo "Found buffer files"
-		find $WORK_DIRECTORY -type f -size +0c -regextype posix-basic -regex ".*/$BASENAME.*\.[0-9]\{8\}"
+		find $WORK_DIRECTORY -type f -size +0c -regextype posix-basic -regex ".*/$BASENAME.*\.[0-9]\{7\}[2-9]"
 		exit $CRITICAL
 	else
 		echo "No buffer files found"
 		exit $OK
 	fi
 fi
+
+if [ $QUEUED_STATS_CHECK -eq 1 ] && [ $FILE -eq 1 ]; then
+
+	RESULT=$(awk "/$BASENAME/ && /$(date +"%b %e")/" $FILENAME | \
+            grep -o ' size=[0-9]\+ ' | tail -1 | awk -F = '{ print $2 }')
+
+	compare $RESULT
+fi

+ 112 - 0
check_sagan.sh

@@ -0,0 +1,112 @@
+#!/usr/bin/env bash
+# Author: Jon Schipp
+# Date: 01-27-2014
+########
+# Examples:
+
+# 1.) Check presence of disk queue (buffer)
+# $ ./check_sagan.sh -T  -q rsyslog -d /var/spool/rsyslog
+
+# Nagios Exit Codes
+OK=0
+WARNING=1
+CRITICAL=2
+UNKNOWN=3
+
+# Default rsyslog spool directory
+FILE=/var/log/sagan/sagan.stats
+usage()
+{
+cat <<EOF
+
+Checks most recent sagan stats preprocessor line for specified thresholds
+
+     Options:
+	-c <int>	 Critical number
+	-w <int>	 Warning number
+	-f <file>	 Set file when using impstats checks
+	-T <type>	 Check type (total/dropped/ignored/signatures)
+				total   - Check total processed messages
+				drop - Check dropped messages
+				ignore - Check gnore matches
+				signature - Check signature matches
+
+Usage: $0 -T dropped
+EOF
+}
+
+compare(){
+local msg=$1
+local count=$2
+
+if [[ $count -gt $CRIT ]]; then
+  echo "CRITICAL: $count $msg"
+  exit $CRITICAL;
+elif [[ $count -gt $WARN ]]; then
+  echo "WARNING: $count $msg"
+  exit $WARNING;
+else
+  echo "OK: $count $msg"
+  exit $OK;
+fi
+}
+
+argcheck(){
+# if less than n argument
+if [ $ARGC -lt $1 ]; then
+        echo "Missing arguments! Use \`\`-h'' for help."
+        exit 1
+fi
+}
+
+# Initialize variables
+ARGC=$#
+TOTAL_CHECK=0
+DROP_CHECK=0
+IGNORE_CHECK=0
+SIG_CHECK=0
+CRIT=0
+WARN=0
+
+argcheck 1
+
+while getopts "hc:w:f:T:" OPTION
+do
+     case $OPTION in
+         h) usage ;;
+	 c) CRIT=$OPTARG ;;
+	 w) WARN=$OPTARG ;;
+         f)
+	   if [[ -r $OPTARG ]]; then
+             FILE="$OPTARG"
+	   else
+	     echo "Does $OPTARG exist and is readable?"
+	     exit $UNKNOWN
+	   fi
+	   ;;
+	 T)
+           if [[ "$OPTARG" == "total" ]]; then
+             TOTAL_CHECK=1
+	   elif [[ "$OPTARG" == "drop" ]]; then
+             DROP_CHECK=1
+	   elif [[ "$OPTARG" == "ignore" ]]; then
+             IGNORE_CHECK=1
+	   elif [[ "$OPTARG" == "signature" ]]; then
+             SIG_CHECK=1
+	   else
+             echo "$OPTARG is not a valid check type"
+             exit $WARNING
+	   fi
+	   ;;
+         \?)
+           exit $WARNING ;;
+     esac
+done
+
+stats_line=$(tail -n 1 $FILE) || { echo "Not able to read $FILE" && exit $UNKNOWN; }
+[[ $stats_line  =~ ^# ]] && echo "Waiting for stats.." && exit $OK
+
+[[ $TOTAL_CHECK -eq 1 ]]  && count=$(echo $stats_line | cut -d , -f2) && compare total $count
+[[ $ISG_CHECK -eq 1 ]]    && count=$(echo $stats_line | cut -d , -f3) && compare signature $count
+[[ $DROP_CHECK -eq 1 ]]   && count=$(echo $stats_line | cut -d , -f7) && compare dropped $count
+[[ $IGNORE_CHECK -eq 1 ]] && count=$(echo $stats_line | cut -d , -f8) && compare ignored $count

+ 109 - 0
check_status_code.sh

@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+
+# Author: Jon Schipp
+
+########
+# Examples:
+
+# 1.) Check status code for uptime using the defaults
+# $ ./check_status_code.sh -r /usr/bin/uptime
+#
+# 2.) Custom service does it backwards and exits 1 when running and 0 when stopped.
+# $ ./check_status_code.sh -r "/usr/sbin/service custom-server status" -o 1 -c 0
+
+# Nagios Exit Codes
+NAGIOS_OK=0
+NAGIOS_WARNING=1
+NAGIOS_CRITICAL=2
+NAGIOS_UNKNOWN=3
+
+# Mutable Nagios Exit Codes
+OK=0
+WARNING=1
+CRITICAL=2
+UNKNOWN=3
+
+usage()
+{
+cat <<EOF
+
+Checks the status, or exit, code of another program and returns a
+Nagios status code based on the result.
+
+     Options:
+        -r <cmd>    Absolute path of program to run, use quotes for options
+        -o <int>    Status to expect for OK state       (def: 0)
+        -w <int>    Status to expect for WARNING state  (def: 1)
+        -c <int>    Status to expect for CRITICAL state (def: 2)
+        -u <int>    Status to expect for UNKNOWN state  (def: 3)
+
+Usage: $0 -r "/usr/sbin/service sshd status"
+EOF
+}
+
+argcheck() {
+# if less than n argument
+if [ $ARGC -lt $1 ]; then
+        echo "Missing arguments! Use \`\`-h'' for help."
+        exit 1
+fi
+}
+
+ARGC=$#
+
+argcheck 1
+
+while getopts "hc:o:r:w:u:" OPTION
+do
+     case $OPTION in
+         h)
+             usage
+             exit 0
+             ;;
+         r)  if ! [ -z $RUN ]; then
+		     echo "Error: Argument \`\`-r'' is required''."
+		     exit 1
+	     else
+		     RUN="$OPTARG"
+	     fi
+             ;;
+         o)
+             OK=$OPTARG
+             ;;
+         w)
+	     WARNING=$OPTARG
+             ;;
+         c)
+	     CRITICAL=$OPTARG
+             ;;
+         u)
+	     UNKNOWN=$OPTARG
+             ;;
+         \?)
+             exit 1
+             ;;
+     esac
+done
+
+COMMAND=$(echo $RUN | sed 's/ .*//')
+
+if ! [ -x $COMMAND ]; then
+	echo "Error: $COMMAND does not exist, is not an absolute path,  or is not executable."
+	exit 1
+fi
+
+$RUN
+
+CODE=$?
+
+if [ $CODE -eq $OK ]; then
+	exit $NAGIOS_OK
+elif [ $CODE -eq $WARNING ]; then
+	exit $NAGIOS_WARNING
+elif [ $CODE -eq $CRITICAL ]; then
+	exit $CRITICAL
+elif [ $CODE -eq $UNKNOWN ]; then
+	exit $NAGIOS_UNKNOWN
+else
+	echo "Exit code not understood: $CODE"
+fi

+ 33 - 41
check_traffic.sh

@@ -2,13 +2,6 @@
 
 # Author: Jon Schipp
 
-########
-# Examples:
-
-# 1.) Check syslog traffic rate
-# $ ./check_traffice.sh -i eth0 -f "port 514" -t 1s -w 500 -c 1000
-
-
 # Nagios Exit Codes
 OK=0
 WARNING=1
@@ -21,13 +14,12 @@ cat <<EOF
 
 Nagios plug-in that checks packet rate for traffic specified with a bpf
 
-      Options:
-
-      -i 		Network interface
-      -f <bpf>		Filter in libpcap syntax
-      -t <int>		Time interval in seconds (def: 1)
-      -w <int>		Warning threshold
-      -c <int>		Critical threshold
+  Options:
+  -i 		Network interface
+  -f <bpf>	Filter in libpcap syntax
+  -t <int>	Time interval in seconds (def: 1)
+  -w <int>	Warning threshold
+  -c <int>	Critical threshold
 
 EOF
 }
@@ -69,11 +61,11 @@ get_counts() {
 
 traffic_calculation() {
 if [ $1 -gt $CRIT ]; then
-	exit $CRITICAL
+  exit $CRITICAL
 elif [ $1 -gt $WARN ]; then
-	exit $WARNING
+  exit $WARNING
 else
-	exit $OK
+  exit $OK
 fi
 }
 
@@ -94,30 +86,30 @@ depend_check
 # option and argument handling
 while getopts "hi:c:f:t:w:" OPTION
 do
-     case $OPTION in
-         h)
-             usage
-             exit
-             ;;
-         i)
-	     INT=$OPTARG
-	     ;;
-	 f)
-	     FILTER="$OPTARG"
-	     ;;
-	 t)
-	     TIME=$OPTARG
-	     ;;
-	 c)
-	     CRIT=$OPTARG
-	     ;;
-	 w)
-	     WARN=$OPTARG
-	     ;;
-	 *)
-	     exit $UNKNOWN
-             ;;
-     esac
+  case $OPTION in
+     h)
+       usage
+       exit
+       ;;
+     i)
+       INT=$OPTARG
+       ;;
+     f)
+       FILTER="$OPTARG"
+       ;;
+     t)
+       TIME=$OPTARG
+       ;;
+     c)
+       CRIT=$OPTARG
+       ;;
+     w)
+       WARN=$OPTARG
+       ;;
+     *)
+       exit $UNKNOWN
+       ;;
+  esac
 done
 
 [ -d /sys/class/net/$INT ] || { "UNKNOWN: $INT does not exist" && exit $UNKNOWN; }

+ 3 - 3
check_volume.sh

@@ -22,7 +22,7 @@ Usage: $0 -v /mnt -c 95 -w 90
 EOF
 }
 
-if [ $# -lt 6 ]; 
+if [ $# -lt 6 ];
 then
 	usage
 	exit 1
@@ -50,7 +50,7 @@ do
          v)
              VOL="$OPTARG"
              ;;
-	 w) 
+	 w)
 	     WARN="$OPTARG"
 	     ;;
          \?)
@@ -83,4 +83,4 @@ elif [ $STATUS -gt $WARN ]; then
 else
         echo "$VOL is at ${STATUS}% capacity, $USED of $SIZE"
         exit $OK
-fi 
+fi