Browse Source

add more nagios-plugins i've written

Jon Schipp 10 years ago
parent
commit
a7d1adb3dd
17 changed files with 1320 additions and 216 deletions
  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
 # Set this to the proper location if your installation differs
 MYRI_COUNTERS=/opt/snf/bin/myri_counters
 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
 # Set this to the proper location if your installation differs
 CAPTURE_LOG=/usr/local/bro/logs/current/capture_loss.log
 CAPTURE_LOG=/usr/local/bro/logs/current/capture_loss.log
+STATS_LOG=/usr/local/bro/logs/current/stats.log
 
 
 usage()
 usage()
 {
 {
@@ -45,25 +46,26 @@ cat <<EOF
 Check status of Bro and Bro workers.
 Check status of Bro and Bro workers.
 This script should be run on the Bro manager.
 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
 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
 $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
 while getopts "hfc:i:lm:p:T:u:w:" OPTION
 do
 do
   case $OPTION in
   case $OPTION in
-    h)
-      usage
-      ;;
+    h) usage;;
     f)
     f)
       shift
       shift
       if [[ $1 == *broctl ]]; then
       if [[ $1 == *broctl ]]; then
@@ -115,6 +115,9 @@ do
         MYRI_COUNTERS=$1
         MYRI_COUNTERS=$1
       elif [[ $1 == *capture_loss.log ]]; then
       elif [[ $1 == *capture_loss.log ]]; then
         CAPTURE_LOG=$1
         CAPTURE_LOG=$1
+      # Custom thing written by jazoff - hopefully integrated into Bro upstream sometime
+      elif [[ $1 == *current/stats.log ]]; then
+        STATS_LOG=$1
       else
       else
         echo "File name appears to be incorrect, maybe try setting the approprate variable in $0."
         echo "File name appears to be incorrect, maybe try setting the approprate variable in $0."
       fi
       fi
@@ -158,14 +161,14 @@ do
       fi
       fi
       ;;
       ;;
     u)
     u)
-        USER="$OPTARG"
-        ;;
+      USER="$OPTARG"
+      ;;
     w)
     w)
-        WARN="$OPTARG"
-        ;;
+      WARN="$OPTARG"
+      ;;
     \?)
     \?)
-        exit 1
-        ;;
+      exit 1
+      ;;
   esac
   esac
 done
 done
 
 
@@ -184,9 +187,8 @@ fi
 
 
 if [ $LOSS_CHECK -eq 1 ]; then
 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
   if [ $LOSS -gt $CRIT ] ;then
     echo "Average packet loss is: $FLOAT_LOSS"
     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
 # Broctl stderr is whitespace separated and we need to match on entire line
 IFS=$'\n'
 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
   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"
     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)))
   RECENT=$(echo $((TIME-INTERVAL)))
 
 
   awk -v recent=$RECENT -v crit=$CRIT -v loss=0 -v threshold=0 '! /^#/ && $1 > recent && $4 > 0 \
   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 {
     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
     else
-      print "\nNo loss detected"; }' $CAPTURE_LOG
+             print "\nNo loss detected"; }' $CAPTURE_LOG
 
 
   if [ $? -eq 2 ]; then
   if [ $? -eq 2 ]; then
     exit $CRITICAL
     exit $CRITICAL
@@ -282,7 +283,6 @@ if [ $PRINT_CHECK -eq 1 ]; then
 fi
 fi
 
 
 if [ $MYRI_CHECK -eq 1 ]; then
 if [ $MYRI_CHECK -eq 1 ]; then
-
 LOSS=0
 LOSS=0
 RECV=0
 RECV=0
 COUNT=0
 COUNT=0

+ 60 - 60
check_connections.sh

@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
 #!/usr/bin/env bash
-
+# Author: Jon Schipp <jonschipp@gmail.com, jschipp@illinois.edu>
 # Nagios Exit Codes
 # Nagios Exit Codes
 OK=0
 OK=0
 WARNING=1
 WARNING=1
@@ -13,14 +13,14 @@ cat <<EOF
 Check the number of connections/sockets in a given state.
 Check the number of connections/sockets in a given state.
 Uses iproute2's ss tool to retrieve connections.
 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
 Usage: $0 -s established '( sport = :443 )' -w 800 -c 1000
 EOF
 EOF
@@ -29,14 +29,14 @@ EOF
 argcheck() {
 argcheck() {
 # if less than n argument
 # if less than n argument
 if [ $ARGC -lt $1 ]; then
 if [ $ARGC -lt $1 ]; then
-        echo "Missing arguments! Use \`\`-h'' for help."
-        exit 1
+  echo "Missing arguments! Use \`\`-h'' for help."
+  exit 1
 fi
 fi
 }
 }
 
 
 if ! command -v ss >/dev/null 2>&1; then
 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
 fi
 
 
 # Define now to prevent expected number errors
 # Define now to prevent expected number errors
@@ -47,60 +47,60 @@ COUNT=0
 ARGC=$#
 ARGC=$#
 CHECK=0
 CHECK=0
 
 
-argcheck 1 
+argcheck 1
 
 
 while getopts "hc:s:f:p:w:" OPTION
 while getopts "hc:s:f:p:w:" OPTION
 do
 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
 done
 
 
 COUNT=$(ss -n state $STATE $PROTOCOL $FILTER | grep -v 'State\|-Q' | wc -l)
 COUNT=$(ss -n state $STATE $PROTOCOL $FILTER | grep -v 'State\|-Q' | wc -l)
 
 
 if [ $COUNT -gt $CRIT ]; then
 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
 elif [ $COUNT -gt $WARN ]; then
-        echo "$COUNT sockets in $STATE state!"
-        exit $WARNING
+  echo "$COUNT sockets in $STATE state!"
+  exit $WARNING
 else
 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
 #!/usr/bin/env python
+# Author: Jon Schipp <jonschipp@gmail.com, jschipp@illinois.edu>
 import sys
 import sys
 import datetime
 import datetime
 import requests
 import requests
@@ -12,7 +13,6 @@ nagios_warning  = 1
 nagios_critical = 2
 nagios_critical = 2
 nagios_unknown  = 3
 nagios_unknown  = 3
 
 
-import argparse
 parser = argparse.ArgumentParser(description='Last Crashplan backup check')
 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("-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)")
 parser.add_argument("-d", "--device", type=str, help="Specify deviceName to check (def: all)")
@@ -38,12 +38,12 @@ else:
 
 
 # Open file
 # Open file
 try:
 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:
 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)
   exit(nagios_unknown)
 
 
 def backup_check(device, orig_time):
 def backup_check(device, orig_time):
@@ -51,7 +51,7 @@ def backup_check(device, orig_time):
   if time < critical_days:
   if time < critical_days:
     print "CRITICAL: %s: LastCompleteBackup: %s" % (device, orig_time)
     print "CRITICAL: %s: LastCompleteBackup: %s" % (device, orig_time)
     status = nagios_critical
     status = nagios_critical
-    
+
 def format_time(entry, orig_time):
 def format_time(entry, orig_time):
   global time
   global time
   time = datetime.datetime.strptime(orig_time, "%b %d, %Y %I:%M:%S %p")
   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)
       backup_check(device, orig_time)
 
 
 # Make API request
 # Make API request
-r = requests.get(url, auth=(creds.user, creds.password))
+r = requests.get(url, auth=(user, password))
 r.raise_for_status()
 r.raise_for_status()
 
 
 data  = r.json()
 data  = r.json()
@@ -87,8 +87,8 @@ if host == 0:
 else:
 else:
  check_host_backup()
  check_host_backup()
 
 
-if status == nagios_critical: 
+if status == nagios_critical:
   exit(nagios_critical)
   exit(nagios_critical)
 else:
 else:
-  print "OK: All backups have been completed recently" 
+  print "OK: All backups have been completed recently"
   exit(nagios_ok)
   exit(nagios_ok)

+ 4 - 4
check_file_growth.sh

@@ -79,7 +79,7 @@ PROG=wc
 OS=$(uname)
 OS=$(uname)
 ARGC=$#
 ARGC=$#
 
 
-argcheck 4 
+argcheck 4
 
 
 while getopts "hc:f:i:M:T:w:" OPTION
 while getopts "hc:f:i:M:T:w:" OPTION
 do
 do
@@ -90,7 +90,7 @@ do
     CRIT="$OPTARG";;
     CRIT="$OPTARG";;
   f)
   f)
     FILE="$OPTARG";;
     FILE="$OPTARG";;
-  i) 
+  i)
     TIME="$OPTARG";;
     TIME="$OPTARG";;
   M)
   M)
     PROG="$OPTARG"
     PROG="$OPTARG"
@@ -113,7 +113,7 @@ do
     	echo "Unknown type!"
     	echo "Unknown type!"
     	exit 1
     	exit 1
     fi;;
     fi;;
-  w) 
+  w)
       WARN="$OPTARG";;
       WARN="$OPTARG";;
   \?)
   \?)
       exit 1;;
       exit 1;;
@@ -142,7 +142,7 @@ fi
 
 
 GROWTH=$(($NEW-$OLD))
 GROWTH=$(($NEW-$OLD))
 
 
-if [[ $CONCERN -eq 0 ]]; then 
+if [[ $CONCERN -eq 0 ]]; then
   if [[ $GROWTH -gt 0 ]]; then
   if [[ $GROWTH -gt 0 ]]; then
     echo "File grew by $GROWTH bytes"
     echo "File grew by $GROWTH bytes"
     exit $OK
     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')
 	UPTIME=$(uptime | awk -F : '{ print $4 }' | sed 's/,//g')
 elif [[ "$OS" == aix ]]; then
 elif [[ "$OS" == aix ]]; then
 	UPTIME=$(uptime | awk -F : '{ print $4 }' | sed 's/,//g')
 	UPTIME=$(uptime | awk -F : '{ print $4 }' | sed 's/,//g')
-else 
+else
 	echo "OS not supported"
 	echo "OS not supported"
 	exit $UNKNOWN
 	exit $UNKNOWN
 fi
 fi
@@ -89,7 +89,7 @@ UNAME=$(uname)
  else
  else
         echo "Unsupported OS type!"
         echo "Unsupported OS type!"
         exit 1
         exit 1
- fi  
+ fi
 
 
 }
 }
 
 
@@ -171,7 +171,7 @@ if [ $THRESHOLD -eq 1 ]; then
 			WARN_STATUS=$((WARN_STATUS+1))
 			WARN_STATUS=$((WARN_STATUS+1))
 		else
 		else
 			OK_STATUS=$((OK_STATUS+1))
 			OK_STATUS=$((OK_STATUS+1))
-		fi	
+		fi
 	done
 	done
 fi
 fi
 
 
@@ -181,7 +181,7 @@ if [ $CRIT_STATUS -gt 0 ]; then
 elif [ $WARN_STATUS -gt 0 ]; then
 elif [ $WARN_STATUS -gt 0 ]; then
 	echo "Load average warning: $UPTIME"
 	echo "Load average warning: $UPTIME"
 	exit $WARNING
 	exit $WARNING
-else 
+else
 	echo "Load average: $UPTIME"
 	echo "Load average: $UPTIME"
 	exit $OK
 	exit $OK
 fi
 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)
          h)
 	     usage
 	     usage
              ;;
              ;;
-	 t) 
+	 t)
 	     MONITOR=1
 	     MONITOR=1
 	     ;;
 	     ;;
-	 c) 
+	 c)
 	     CRIT="$OPTARG"
 	     CRIT="$OPTARG"
 	     ;;
 	     ;;
-	 w) 
+	 w)
 	     WARN="$OPTARG"
 	     WARN="$OPTARG"
 	     ;;
 	     ;;
          \?)
          \?)
@@ -68,11 +68,11 @@ done
 if [ $MONITOR -eq 1 ]; then
 if [ $MONITOR -eq 1 ]; then
 	$COMMAND | sed 's/ F//' | awk -v crit=$CRIT -F : \
 	$COMMAND | sed 's/ F//' | awk -v crit=$CRIT -F : \
 	'$2 > crit { high=1; print $0 }
 	'$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
 #!/usr/bin/env bash
-
+# awk '{ for( i=NF; i>=1; i--) print $i }'
 # Author: Jon Schipp
 # Author: Jon Schipp
 # Date: 01-27-2014
 # Date: 01-27-2014
 ########
 ########
 # Examples:
 # Examples:
 
 
 # 1.) Check presence of disk queue (buffer)
 # 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
 # Nagios Exit Codes
 OK=0
 OK=0
@@ -14,7 +17,7 @@ WARNING=1
 CRITICAL=2
 CRITICAL=2
 UNKNOWN=3
 UNKNOWN=3
 
 
-# Default rsyslog spool directory 
+# Default rsyslog spool directory
 WORK_DIRECTORY=/var/spool/rsyslog
 WORK_DIRECTORY=/var/spool/rsyslog
 
 
 usage()
 usage()
@@ -22,13 +25,33 @@ usage()
 cat <<EOF
 cat <<EOF
 
 
      Options:
      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
 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() {
 argcheck() {
 # if less than n argument
 # if less than n argument
 if [ $ARGC -lt $1 ]; then
 if [ $ARGC -lt $1 ]; then
@@ -40,25 +63,46 @@ fi
 # Initialize variables
 # Initialize variables
 ARGC=$#
 ARGC=$#
 QUEUE_CHECK=0
 QUEUE_CHECK=0
+QUEUED_STATS_CHECK=0
+FILE=0
+CRIT=0
+WARN=0
 
 
 argcheck 1
 argcheck 1
 
 
-while getopts "hd:q:" OPTION
+while getopts "hc:w:f:d:q:T:" OPTION
 do
 do
      case $OPTION in
      case $OPTION in
-         h)
-             usage
-             ;;
+         h) usage ;;
+	 c) CRIT=$OPTARG ;;
+	 w) WARN=$OPTARG ;;
 	 d)
 	 d)
 	     WORK_DIRECTORY=$(echo $OPTARG | sed 's/\/$//')
 	     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)
          q)
              BASENAME=$OPTARG
              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
      esac
 done
 done
 
 
@@ -67,14 +111,22 @@ if [ $QUEUE_CHECK -eq 1 ]; then
 	# Remove stale 0 byte queue files
 	# Remove stale 0 byte queue files
 	# find $WORK_DIRECTORY -type f -size 0c -regextype posix-basic -regex ".*/$BASENAME.*\.[0-9]\{8\}" | xargs rm -rf
 	# 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
 	if [ $COUNT -gt 0 ]; then
 		echo "Found buffer files"
 		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
 		exit $CRITICAL
 	else
 	else
 		echo "No buffer files found"
 		echo "No buffer files found"
 		exit $OK
 		exit $OK
 	fi
 	fi
 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
 # 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
 # Nagios Exit Codes
 OK=0
 OK=0
 WARNING=1
 WARNING=1
@@ -21,13 +14,12 @@ cat <<EOF
 
 
 Nagios plug-in that checks packet rate for traffic specified with a bpf
 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
 EOF
 }
 }
@@ -69,11 +61,11 @@ get_counts() {
 
 
 traffic_calculation() {
 traffic_calculation() {
 if [ $1 -gt $CRIT ]; then
 if [ $1 -gt $CRIT ]; then
-	exit $CRITICAL
+  exit $CRITICAL
 elif [ $1 -gt $WARN ]; then
 elif [ $1 -gt $WARN ]; then
-	exit $WARNING
+  exit $WARNING
 else
 else
-	exit $OK
+  exit $OK
 fi
 fi
 }
 }
 
 
@@ -94,30 +86,30 @@ depend_check
 # option and argument handling
 # option and argument handling
 while getopts "hi:c:f:t:w:" OPTION
 while getopts "hi:c:f:t:w:" OPTION
 do
 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
 done
 
 
 [ -d /sys/class/net/$INT ] || { "UNKNOWN: $INT does not exist" && exit $UNKNOWN; }
 [ -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
 EOF
 }
 }
 
 
-if [ $# -lt 6 ]; 
+if [ $# -lt 6 ];
 then
 then
 	usage
 	usage
 	exit 1
 	exit 1
@@ -50,7 +50,7 @@ do
          v)
          v)
              VOL="$OPTARG"
              VOL="$OPTARG"
              ;;
              ;;
-	 w) 
+	 w)
 	     WARN="$OPTARG"
 	     WARN="$OPTARG"
 	     ;;
 	     ;;
          \?)
          \?)
@@ -83,4 +83,4 @@ elif [ $STATUS -gt $WARN ]; then
 else
 else
         echo "$VOL is at ${STATUS}% capacity, $USED of $SIZE"
         echo "$VOL is at ${STATUS}% capacity, $USED of $SIZE"
         exit $OK
         exit $OK
-fi 
+fi