mirror of
https://github.com/munin-monitoring/contrib.git
synced 2018-11-08 00:59:34 +01:00
remove plugins existing in main munin repository
This commit is contained in:
parent
331d5a43dc
commit
accf47f9a0
@ -1,55 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Monitor disk iostat on FreeBSD host.
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# config (required)
|
||||
# autoconf (optional - used by munin-config)
|
||||
#
|
||||
# Magic markers (optional - used by munin-config and installation
|
||||
# scripts):
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
echo yes
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DISKS=`/usr/sbin/iostat -dIn9 | head -1`
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
echo 'graph_title IOstat'
|
||||
echo 'graph_args --base 1024 -l 0'
|
||||
echo 'graph_vlabel Bytes per ${graph_period}'
|
||||
echo 'graph_category disk'
|
||||
echo 'graph_info This graph shows disk load on the machine.'
|
||||
|
||||
for D in $DISKS
|
||||
do
|
||||
if echo $D | grep -vq '^pass'; then
|
||||
echo "$D.label $D"
|
||||
echo "$D.type DERIVE"
|
||||
echo "$D.min 0"
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
VALUES=`/usr/sbin/iostat -dIn9 | tail -1`
|
||||
COL=3 # 3rd value for each disk is grabbed
|
||||
|
||||
for D in $DISKS
|
||||
do
|
||||
if echo $D | grep -vq '^pass'; then
|
||||
echo -n "$D.value "
|
||||
VAL=`echo $VALUES | cut -d ' ' -f $COL`
|
||||
echo "$VAL 1048576 * p" | dc | cut -d '.' -f 1
|
||||
fi
|
||||
COL=$(($COL + 3))
|
||||
done
|
@ -1,78 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Plugin to monitor all S.M.A.R.T. capable disks
|
||||
# author: paulv@dds.nl / paulv@bikkel.org
|
||||
# licence : public domain
|
||||
#
|
||||
# Usage: copy or link into /etc/munin/plugins/ as smart_[device] ( smart_sg0 for example)
|
||||
# Run as root
|
||||
#
|
||||
# Parameters:
|
||||
#
|
||||
# config (required)
|
||||
# autoconf (optional - used by munin-config)
|
||||
#
|
||||
# Magic markers (optional - used by munin-config and some installation
|
||||
# scripts):
|
||||
#
|
||||
#%# family=manual
|
||||
#%# capabilities=autoconf
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
my $device = "/dev/$1" if ( $0 =~ /[\w_-]+_(\w+\d+)$/ );
|
||||
my $smartctl = 'smartctl';
|
||||
my $smartctl_param = ' --attributes ';
|
||||
my %attr;
|
||||
|
||||
if ( $ARGV[0] and $ARGV[0] eq "autoconf" ) {
|
||||
|
||||
print "yes\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
open(SMART,"$smartctl $smartctl_param $device |") || die $!;
|
||||
|
||||
while(<SMART>) {
|
||||
chop;
|
||||
if ( m/\s*(\d+)\s+([\w_-]+)\s+(\d+x.+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\w_-]+)\s+(\w+)\s+([\w_-]+)\s+(\d+)/ ) {
|
||||
my $key = $1 . '_' . $2;
|
||||
my $rawvalue = $10;
|
||||
|
||||
$key = "170_Reserved_Block_Count" if $key eq "170_Unknown_Attribute";
|
||||
$key = "171_Program_Fail_Count" if $key eq "171_Unknown_Attribute";
|
||||
$key = "172_Erase_Fail_Count" if $key eq "172_Unknown_Attribute";
|
||||
$key = "173_Wear_Leveling_Count" if $key eq "173_Unknown_Attribute";
|
||||
$key = "174_Unexpected_Pwr_Loss" if $key eq "174_Unknown_Attribute";
|
||||
$key = "189_High_Fly_Writes" if $key eq "189_Unknown_Attribute";
|
||||
$key = "202_TA_Increase_Count" if $key eq "202_Unknown_Attribute";
|
||||
$key = "206_Flying_Height" if $key eq "206_Unknown_Attribute";
|
||||
|
||||
$attr{$key} = $rawvalue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( $ARGV[0] and $ARGV[0] eq "config" )
|
||||
{
|
||||
|
||||
print "graph_title SMART values for $device\n";
|
||||
print "graph_args --base 1000 -l 0\n";
|
||||
print "graph_category disk\n";
|
||||
print "graph_vlabel value\n";
|
||||
print "graph_scale no\n";
|
||||
print "graph_total Total\n";
|
||||
foreach my $i (keys %attr)
|
||||
{
|
||||
print "$i.label smartattribute $i\n";
|
||||
print "$i.draw LINE2\n";
|
||||
print "$i.min 0\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
foreach my $k (keys %attr) {
|
||||
print $k . ".value " . $attr{$k} . "\n";
|
||||
}
|
||||
# end
|
@ -1,52 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
DISK=${0/*smart-by-id_/}
|
||||
SMARTCTL="`which smartctl | head -1` $SMARTOPTS"
|
||||
|
||||
echo "# $DISK"
|
||||
|
||||
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
case $1 in
|
||||
config)
|
||||
echo 'graph_title S.M.A.R.T values for drive '`readlink -f /dev/disk/by-id/$DISK`
|
||||
echo 'graph_vlabel Attribute S.M.A.R.T value'
|
||||
echo 'graph_args --base 1000 --lower-limit 0'
|
||||
echo 'graph_category disk'
|
||||
echo 'graph_info This graph shows the value of all S.M.A.R.T attributes of drive '`$SMARTCTL -i /dev/disk/by-id/$DISK | grep -Ei 'model|serial|firmware' | sed -re 's/.+?: +//gm' | tr '\n' ' '`
|
||||
echo 'smartctl_exit_status.label smartctl exit value'
|
||||
echo 'smartctl_exit_status.draw LINE2'
|
||||
echo 'smartctl_exit_class.label smartctl exit status'
|
||||
echo 'smartctl_exit_class.draw AREA'
|
||||
echo 'smartctl_exit_class.warning :0'
|
||||
echo 'smartctl_exit_class.critical :1'
|
||||
|
||||
$SMARTCTL -A /dev/disk/by-id/$DISK | grep 0x | while read
|
||||
do
|
||||
OP=($REPLY)
|
||||
ON=`echo -n ${OP[1]} | tr -c '[A-z0-9]' '_'`
|
||||
OL=`echo -n ${OP[1]} | tr '_' ' '`
|
||||
echo ${ON}.label ${OL}
|
||||
echo ${ON}.draw LINE2
|
||||
echo ${ON}.critical ${OP[5]}:
|
||||
done
|
||||
;;
|
||||
suggest)
|
||||
ls -1 /dev/disk/by-id/scsi-* | grep -v part | grep -o scsi.*
|
||||
;;
|
||||
"")
|
||||
$SMARTCTL -a /dev/disk/by-id/$DISK &> /dev/null
|
||||
SES=$?
|
||||
echo "smartctl_exit_status.value $SES"
|
||||
if [ $SES -gt 0 ]
|
||||
then
|
||||
if [ $((SES & 7)) -gt 0 ] ; then exit 1 ; fi
|
||||
if [ $((SES & 24)) -gt 0 ] ; then SES=2 ; fi
|
||||
if [ $((SES & 224)) -gt 0 ] ; then SES=1 ; fi
|
||||
fi
|
||||
echo "smartctl_exit_class.value $SES"
|
||||
$SMARTCTL -A /dev/disk/by-id/$DISK | awk '/0x/ { gsub(/[^a-zA-Z0-9]/,"_",$2); print $2.".value",$4; }'
|
||||
;;
|
||||
esac
|
||||
|
||||
#exit 0
|
@ -1,585 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: iso-8859-1 -*-
|
||||
#
|
||||
# Wildcard-plugin to monitor S.M.A.R.T attribute values through smartctl,
|
||||
# which is part of smartmontools package:
|
||||
# http://smartmontools.sourceforge.net/
|
||||
#
|
||||
# To monitor a S.M.A.R.T device, link smart_<device> to this file.
|
||||
# E.g.
|
||||
# ln -s /usr/share/munin/plugins/smart_ /etc/munin/plugins/smart_hda
|
||||
# ...will monitor /dev/hda.
|
||||
#
|
||||
# Needs following minimal configuration in plugin-conf.d/munin-node:
|
||||
# [smart_*]
|
||||
# user root
|
||||
# group disk
|
||||
#
|
||||
# Parameters
|
||||
# smartpath - Specify path to smartctl program (Default: /usr/sbin/smartctl)
|
||||
# smartargs - Override '-a' argument passed to smartctl with '-A -i'+smartargs
|
||||
# ignorestandby - Ignore the standby state of the drive and perform SMART query. Default: False
|
||||
#
|
||||
# Parameters can be specified on a per-drive basis, eg:
|
||||
# [smart_hda]
|
||||
# user root
|
||||
# group disk
|
||||
# env.smartargs -H -c -l error -l selftest -l selective -d ata
|
||||
# env.smartpath /usr/local/sbin/smartctl
|
||||
#
|
||||
# [smart_twa0-1]
|
||||
# user root
|
||||
# group disk
|
||||
# env.smartargs -H -l error -d 3ware,1
|
||||
# env.ignorestandby True
|
||||
#
|
||||
# [smart_twa0-2]
|
||||
# user root
|
||||
# group disk
|
||||
# env.smartargs -H -l error -d 3ware,2
|
||||
#
|
||||
# Author: Nicolas Stransky <Nico@neo-lan.net>
|
||||
#
|
||||
# v1.0 22/08/2004 - First draft
|
||||
# v1.2 28/08/2004 - Clean up the code, add a verbose option
|
||||
# v1.3 14/11/2004 - Compatibility with python<2.2. See comments in the code
|
||||
# v1.4 17/11/2004 - Deal with non zero exit codes of smartctl
|
||||
# - config now prints the critical thresholds, as reported by smartctl
|
||||
# v1.5 18/11/2004 - Plot smartctl_exit_code bitmask
|
||||
# v1.6 21/11/2004 - Add autoconf and suggest capabilities
|
||||
# - smartctl path can be passed through "smartpath" environment variable
|
||||
# - Additional smartctl args can be passed through "smartargs" environment variable
|
||||
# v1.7 29/11/2004 - Add suggest capabilities for NetBSD, OpenBSD, FreeBSD and SunOS.
|
||||
# - Allow to override completely the smartctl arguments with "smartargs"
|
||||
# v1.8 16/02/2005 - Exit status field now only triggers warnings, not criticals.
|
||||
# v1.9 07/07/2005 - Allow to query several drives on the same 3ware card.
|
||||
# - Correct a bug when '-i' was not listed in smartargs
|
||||
# - Don't fail if no value was obtained for hard drive model
|
||||
# v1.10 19/08/2005 - smartctl_exit_code is now a numerical value
|
||||
# v2.0 08/05/2009 - Correct bug in the interpretation of smartctl_exit_code
|
||||
# - New option to suppress SMART warnings in munin
|
||||
# - Temporary lack of output for previously existing drive now reports U
|
||||
# - The plugin now contains its own documentation for use with munindoc
|
||||
# - Removed python<2.2 compatibility comments
|
||||
# - Better autodetection of drives
|
||||
# - Don't spin up devices in a low-power mode.
|
||||
#
|
||||
# Copyright (c) 2004-2009 Nicolas Stransky.
|
||||
#
|
||||
# Permission to use, copy, and modify this software with or without fee
|
||||
# is hereby granted, provided that this entire notice is included in
|
||||
# all source code copies of any software which is or includes a copy or
|
||||
# modification of this software.
|
||||
#
|
||||
# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
|
||||
# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
|
||||
# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
|
||||
# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
|
||||
# PURPOSE.
|
||||
#
|
||||
#
|
||||
# Magic markers
|
||||
#%# capabilities=autoconf suggest
|
||||
#%# family=auto
|
||||
|
||||
## You may edit the following 3 variables
|
||||
# Increase verbosity (True/False)
|
||||
verbose=False
|
||||
# Suppress SMART warnings (True/False)
|
||||
report_warnings=True
|
||||
# Modify to your needs:
|
||||
statefiledir='/var/lib/munin/plugin-state/'
|
||||
# You may not modify anything below this line
|
||||
|
||||
import os, sys, string, pickle
|
||||
from math import log
|
||||
plugin_version="2.0"
|
||||
|
||||
def verboselog(s):
|
||||
global plugin_name
|
||||
sys.stderr.write(plugin_name+': '+s+'\n')
|
||||
|
||||
if not verbose :
|
||||
verboselog = lambda s: None
|
||||
|
||||
def read_values(hard_drive):
|
||||
global smart_values, emptyoutput
|
||||
try :
|
||||
verboselog('Reading S.M.A.R.T values')
|
||||
os.putenv('LC_ALL','C')
|
||||
smart_output=os.popen(os.getenv('smartpath','/usr/sbin/smartctl')+' '+os.getenv('smartargs','-a')+(os.getenv('ignorestandby',False) and ' ' or ' -n standby ')+'-A -i /dev/'+hard_drive)
|
||||
read_values=0
|
||||
for l in smart_output :
|
||||
if l[:-1]=='' :
|
||||
read_values=0
|
||||
elif l[:13]=='Device Model:' or l[:7]=='Device:' :
|
||||
model_list=string.split(string.split(l,':')[1])
|
||||
try: model_list.remove('Version')
|
||||
except : None
|
||||
model=string.join(model_list)
|
||||
if read_values==1 :
|
||||
smart_attribute=string.split(l)
|
||||
smart_values[string.replace(smart_attribute[1],'-','_')]={"value":smart_attribute[3],"threshold":smart_attribute[5]}
|
||||
elif l[:18]=="ID# ATTRIBUTE_NAME" :
|
||||
# Start reading the Attributes block
|
||||
read_values=1
|
||||
exit_status=smart_output.close()
|
||||
if exit_status!=None :
|
||||
# smartctl exit code is a bitmask, check man page.
|
||||
num_exit_status=int(exit_status/256) # Python convention
|
||||
if int(log(num_exit_status,2))<=2 : # bit code
|
||||
verboselog('smartctl cannot access S.M.A.R.T values on drive '+hard_drive+'. Command exited with code '+str(num_exit_status)+' (bit '+str(int(log(num_exit_status,2)))+')')
|
||||
else :
|
||||
verboselog('smartctl exited with code '+str(num_exit_status)+' (bit '+str(int(log(num_exit_status,2)))+'). '+hard_drive+' may be FAILING RIGHT NOW!')
|
||||
else :
|
||||
num_exit_status=0
|
||||
except :
|
||||
verboselog('Cannot access S.M.A.R.T values! Check user rights or propper smartmontools installation/arguments.')
|
||||
sys.exit(1)
|
||||
if smart_values=={} :
|
||||
verboselog('Can\'t find any S.M.A.R.T values in smartctl output!')
|
||||
emptyoutput=True
|
||||
#sys.exit(1)
|
||||
else : emptyoutput=False
|
||||
smart_values["smartctl_exit_status"]={"value":str(num_exit_status),"threshold":"1"}
|
||||
try : smart_values["model"]=model
|
||||
# For some reason we may have no value for "model"
|
||||
except : smart_values["model"]="unknown"
|
||||
return(exit_status)
|
||||
|
||||
def open_state_file(hard_drive,mode) :
|
||||
global statefiledir
|
||||
return open(statefiledir+'/smart-'+string.join(hard_drive,"-")+'.state',mode)
|
||||
|
||||
def update_state_file(hard_drive) :
|
||||
try:
|
||||
verboselog('Saving statefile')
|
||||
pickle.dump(smart_values,open_state_file(hard_drive,"w"))
|
||||
except :
|
||||
verboselog('Error trying to save state file! Check access rights')
|
||||
|
||||
def print_plugin_values(hard_drive) :
|
||||
global emptyoutput, smart_values
|
||||
if not emptyoutput:
|
||||
verboselog('Printing S.M.A.R.T values')
|
||||
for key in smart_values.keys() :
|
||||
if key=="model" : continue
|
||||
print(key+".value "+smart_values[key]["value"])
|
||||
else:
|
||||
print_unknown_from_statefile(hard_drive,smart_values)
|
||||
|
||||
def print_config(hard_drive) :
|
||||
global report_warnings, smart_values, statefiledir
|
||||
if os.path.exists(statefiledir+'/smart-'+string.join(hard_drive,"-")+'.state'):
|
||||
try :
|
||||
verboselog('Try to recall previous S.M.A.R.T attributes for '+string.join(hard_drive,","))
|
||||
smart_values_state=pickle.load(open_state_file(hard_drive,"r"))
|
||||
except :
|
||||
verboselog('Error opening existing state file!')
|
||||
sys.exit(1)
|
||||
else :
|
||||
verboselog('No state file, reading S.M.A.R.T values for the first time')
|
||||
read_values(hard_drive[0])
|
||||
pickle.dump(smart_values,open_state_file(hard_drive,"w"))
|
||||
smart_values_state=smart_values
|
||||
|
||||
verboselog('Printing configuration')
|
||||
print('graph_title S.M.A.R.T values for drive '+string.join(hard_drive,","))
|
||||
print('graph_vlabel Attribute S.M.A.R.T value')
|
||||
print('graph_args --base 1000 --lower-limit 0')
|
||||
print('graph_category disk')
|
||||
print('graph_info This graph shows the value of all S.M.A.R.T attributes of drive '+string.join(hard_drive,",")+' ('+smart_values_state['model']+'). smartctl_exit_status is the return value of smartctl. A non-zero return value indicates an error, a potential error, or a fault on the drive.')
|
||||
attributes=smart_values_state.keys()
|
||||
attributes.sort()
|
||||
for key in attributes :
|
||||
if key in ['smartctl_exit_status','model'] : continue
|
||||
print(key+'.label '+key)
|
||||
print(key+'.draw LINE2')
|
||||
if report_warnings: print(key+'.critical '+smart_values_state[key]["threshold"]+':')
|
||||
print('smartctl_exit_status.label smartctl_exit_status')
|
||||
print('smartctl_exit_status.draw LINE2')
|
||||
if report_warnings: print('smartctl_exit_status.warning '+smart_values_state['smartctl_exit_status']["threshold"])
|
||||
|
||||
def print_unknown_from_statefile(hard_drive,smart_values) :
|
||||
global statefiledir
|
||||
if os.path.exists(statefiledir+'/smart-'+string.join(hard_drive,"-")+'.state'):
|
||||
try :
|
||||
verboselog('Failed to get S.M.A.R.T values from drive. Try to recall previous S.M.A.R.T attributes for '+string.join(hard_drive,","))
|
||||
smart_values_state=pickle.load(open_state_file(hard_drive,"r"))
|
||||
except :
|
||||
verboselog('Error opening existing state file!')
|
||||
sys.exit(1)
|
||||
else :
|
||||
verboselog('No state file, reading S.M.A.R.T values for the first time')
|
||||
exit(1)
|
||||
|
||||
verboselog('Printing unknown values for all attributes in state file')
|
||||
attributes=smart_values_state.keys()
|
||||
attributes.sort()
|
||||
for key in attributes :
|
||||
if key=='model' : continue
|
||||
print(key+'.value U')
|
||||
|
||||
def get_hard_drive_name() :
|
||||
global plugin_name
|
||||
try :
|
||||
name=[plugin_name[string.rindex(plugin_name,'_')+1:]]
|
||||
if os.uname()[0]=="SunOS" :
|
||||
try :
|
||||
# if hard_drive name starts with "rdsk" or "rmt", try to reconstruct the path
|
||||
if name[0][0:4]=="rdsk":
|
||||
name[0]=os.path.join("rdsk",name[0][4:])
|
||||
elif name[0][0:3]=="rmt":
|
||||
name[0]=os.path.join("rmt",name[0][3:])
|
||||
except :
|
||||
verboselog('Failed to find SunOS hard_drive')
|
||||
# For 3ware cards, we have to set multiple plugins for the same hard drive name.
|
||||
# Let's see if we find a '-' in the drive name.
|
||||
if name[0].find('-')!=-1:
|
||||
# Put the drive name and it's number in a list
|
||||
name=[name[0][:string.rindex(name[0],'-')],name[0][string.rindex(name[0],'-')+1:]]
|
||||
# Chech that the drive exists in /dev
|
||||
if not os.path.exists('/dev/'+name[0]):
|
||||
verboselog('/dev/'+name[0]+' not found!')
|
||||
sys.exit(1)
|
||||
return(name)
|
||||
except :
|
||||
verboselog('No S.M.A.R.T device name found in plugin\'s symlink!')
|
||||
sys.exit(1)
|
||||
|
||||
def find_smart_drives() :
|
||||
global emptyoutput
|
||||
# Try to autodetect Linux, *BSD, SunOS drives. Don't try to autodetect drives on a 3Ware card.
|
||||
drives=[]
|
||||
if os.uname()[0]=="Linux" :
|
||||
if os.path.exists('/sys/block/'):
|
||||
# Running 2.6
|
||||
try :
|
||||
for drive in os.listdir('/sys/block/') :
|
||||
if drive[:2] in ['md','fd','lo','ra','dm'] : continue # Ignore MD, Floppy, loop , RAM and LVM devices.
|
||||
try :
|
||||
verboselog('Trying '+drive+'...')
|
||||
exit_status=read_values(drive)
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append(drive)
|
||||
except :
|
||||
continue
|
||||
except :
|
||||
verboselog('Failed to list devices in /sys/block')
|
||||
else :
|
||||
verboselog('Not running linux2.6, failing back to /proc/partitions')
|
||||
try :
|
||||
partitions=open('/proc/partitions','r')
|
||||
L=partitions.readlines()
|
||||
for l in L :
|
||||
words=string.split(l)
|
||||
if len(words)==0 or words[0][0] not in string.digits : continue
|
||||
if words[0] in ['1','9','58','254'] : continue # Ignore RAM, md, LVM and LVM2 devices
|
||||
if words[-1][-1] not in string.digits :
|
||||
try :
|
||||
verboselog('Trying '+words[-1]+'...')
|
||||
exit_status=read_values(words[-1])
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append(words[-1])
|
||||
except :
|
||||
continue
|
||||
verboselog('Found drives in /proc/partitions ! '+str(drives))
|
||||
except :
|
||||
verboselog('Failed to list devices in /proc/partitions')
|
||||
elif os.uname()[0]=="OpenBSD" :
|
||||
try :
|
||||
sysctl_kerndisks=os.popen('sysctl hw.disknames')
|
||||
kerndisks=string.strip(sysctl_kerndisks.readline())
|
||||
for drive in string.split(kerndisks[string.rindex(kerndisks,'=')+1:],',') :
|
||||
if drive[:2] in ['md','cd','fd'] : continue # Ignore Memory Disks, CD-ROM drives and Floppy
|
||||
try :
|
||||
verboselog('Trying '+drive+'c...')
|
||||
exit_status=read_values(drive+'c')
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append(drive+'c')
|
||||
except :
|
||||
continue
|
||||
except :
|
||||
verboselog('Failed to list OpenBSD disks')
|
||||
elif os.uname()[0]=="FreeBSD" :
|
||||
try :
|
||||
sysctl_kerndisks=os.popen('sysctl kern.disks')
|
||||
kerndisks=string.strip(sysctl_kerndisks.readline())
|
||||
for drive in string.split(kerndisks)[1:] :
|
||||
if drive[:2] in ['md','cd','fd'] : continue # Ignore Memory Disks, CD-ROM drives and Floppy
|
||||
try :
|
||||
verboselog('Trying '+drive+'...')
|
||||
exit_status=read_values(drive)
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append(drive)
|
||||
except :
|
||||
continue
|
||||
except :
|
||||
verboselog('Failed to list FreeBSD disks')
|
||||
elif os.uname()[0]=="NetBSD" :
|
||||
try :
|
||||
sysctl_kerndisks=os.popen('sysctl hw.disknames')
|
||||
kerndisks=string.strip(sysctl_kerndisks.readline())
|
||||
for drive in string.split(kerndisks)[2:] :
|
||||
if drive[:2] in ['md','cd','fd'] : continue # Ignore Memory Disks, CD-ROM drives and Floppy
|
||||
try :
|
||||
verboselog('Trying '+drive+'c...')
|
||||
exit_status=read_values(drive+'c')
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append(drive+'c')
|
||||
except :
|
||||
continue
|
||||
except :
|
||||
verboselog('Failed to list NetBSD disks')
|
||||
elif os.uname()[0]=="SunOS" :
|
||||
try :
|
||||
from glob import glob
|
||||
for drivepath in glob('/dev/rdsk/*s2') :
|
||||
try :
|
||||
drive=os.path.basename(drivepath)
|
||||
verboselog('Trying rdsk'+drive+'...')
|
||||
exit_status=read_values('rdsk'+drive)
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append('rdsk'+drive)
|
||||
except :
|
||||
continue
|
||||
for drivepath in glob('/dev/rmt/*') :
|
||||
try :
|
||||
drive=os.path.basename(drivepath)
|
||||
verboselog('Trying rmt'+drive+'...')
|
||||
exit_status=read_values('rmt'+drive)
|
||||
if (exit_status==None or int(log(int(exit_status/256),2))>2) and not emptyoutput:
|
||||
drives.append('rmt'+drive)
|
||||
except :
|
||||
continue
|
||||
except :
|
||||
verboselog('Failed to list SunOS disks')
|
||||
return(drives)
|
||||
|
||||
### Main part ###
|
||||
|
||||
smart_values={}
|
||||
emptyoutput=False
|
||||
plugin_name=list(os.path.split(sys.argv[0]))[1]
|
||||
verboselog('plugins\' UID: '+str(os.geteuid())+' / plugins\' GID: '+str(os.getegid()))
|
||||
|
||||
# Parse arguments
|
||||
if len(sys.argv)>1 :
|
||||
if sys.argv[1]=="config" :
|
||||
hard_drive=get_hard_drive_name()
|
||||
print_config(hard_drive)
|
||||
sys.exit(0)
|
||||
elif sys.argv[1]=="autoconf" :
|
||||
if os.path.exists(os.getenv('smartpath','/usr/sbin/smartctl')) :
|
||||
print('yes')
|
||||
sys.exit(0)
|
||||
else :
|
||||
print('no (smartmontools not found)')
|
||||
sys.exit(1)
|
||||
elif sys.argv[1]=="suggest" :
|
||||
for drive in find_smart_drives() :
|
||||
print(drive)
|
||||
sys.exit(0)
|
||||
elif sys.argv[1]=="version" :
|
||||
print('smart_ Munin plugin, version '+plugin_version)
|
||||
sys.exit(0)
|
||||
elif sys.argv[1]!="" :
|
||||
verboselog('unknown argument "'+sys.argv[1]+'"')
|
||||
sys.exit(1)
|
||||
|
||||
# No argument given, doing the real job:
|
||||
hard_drive=get_hard_drive_name()
|
||||
read_values(hard_drive[0])
|
||||
if not emptyoutput: update_state_file(hard_drive)
|
||||
print_plugin_values(hard_drive)
|
||||
exit(0)
|
||||
|
||||
|
||||
### The following is the smart_ plugin documentation, intended to be used with munindoc
|
||||
"""
|
||||
=head1 NAME
|
||||
|
||||
smart_ - Munin wildcard-plugin to monitor S.M.A.R.T. attribute values through smartctl
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
Node with B<Python> interpreter and B<smartmontools> (http://smartmontools.sourceforge.net/)
|
||||
installed and in function.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
=head2 Create link in service directory
|
||||
|
||||
To monitor a S.M.A.R.T device, create a link in the service directory
|
||||
of the munin-node named smart_<device>, which is pointing to this file.
|
||||
|
||||
E.g.
|
||||
|
||||
ln -s /usr/share/munin/plugins/smart_ /etc/munin/plugins/smart_hda
|
||||
|
||||
...will monitor /dev/hda.
|
||||
|
||||
=head2 Grant privileges in munin-node
|
||||
|
||||
The plugin must be run under high privileged user B<root>, to get access to the raw device.
|
||||
|
||||
So following minimal configuration in plugin-conf.d/munin-node is needed.
|
||||
|
||||
=over 2
|
||||
|
||||
[smart_*]
|
||||
user root
|
||||
group disk
|
||||
|
||||
=back
|
||||
|
||||
=head2 Set Parameter if needed
|
||||
|
||||
smartpath - Specify path to smartctl program (Default: /usr/sbin/smartctl)
|
||||
smartargs - Override '-a' argument passed to smartctl with '-A -i'+smartargs
|
||||
ignorestandby - Ignore the standby state of the drive and perform SMART query. Default: False
|
||||
|
||||
Parameters can be specified on a per-drive basis, eg:
|
||||
|
||||
=over 2
|
||||
|
||||
[smart_hda]
|
||||
user root
|
||||
env.smartargs -H -c -l error -l selftest -l selective -d ata
|
||||
env.smartpath /usr/local/sbin/smartctl
|
||||
|
||||
=back
|
||||
|
||||
In particular, for SATA drives, with older versions of smartctl:
|
||||
|
||||
=over 2
|
||||
|
||||
[smart_sda]
|
||||
user root
|
||||
env.smartargs -d ata -a
|
||||
|
||||
[smart_twa0-1]
|
||||
user root
|
||||
env.smartargs -H -l error -d 3ware,1
|
||||
env.ignorestandby True
|
||||
|
||||
[smart_twa0-2]
|
||||
user root
|
||||
env.smartargs -H -l error -d 3ware,2
|
||||
|
||||
=back
|
||||
|
||||
=head1 INTERPRETATION
|
||||
|
||||
If a device supports the B<Self-Monitoring, Analysis
|
||||
and Reporting Technology (S.M.A.R.T.)> it offers readable
|
||||
access to the attribute table. There you find the B<raw value>,
|
||||
a B<normalised value> and a B<threshold> (set by the vendor)
|
||||
for each attribute, that is supported by that device.
|
||||
|
||||
The meaning and handling of the raw value is a secret of the
|
||||
vendors embedded S.M.A.R.T.-Software on the disk. The only
|
||||
relevant info from our external view is the B<normalised value>
|
||||
in comparison with the B<threshold>. If the attributes value is
|
||||
equal or below the threshold, it signals its failure and
|
||||
the B<health status> of the device will switch from B<passed> to B<failed>.
|
||||
|
||||
This plugin fetches the B<normalised values of all SMART-Attributes>
|
||||
and draw a curve for each of them.
|
||||
It takes the vendors threshold as critical limit for the munin datafield.
|
||||
So you will see an alarm, if the value reaches the vendors threshold.
|
||||
|
||||
Looking at the graph: It is a bad sign, if the curve starts
|
||||
to curl or to meander. The more horizontal it runs,
|
||||
the better. Of course it is normal, that the temperatures
|
||||
curve swings a bit. But the others should stay steady on
|
||||
their level if everything is ok.
|
||||
|
||||
S.M.A.R.T. distinguishes between B<Pre-fail> and B<Old-age>
|
||||
Attributes. An old disk will have more curling curves
|
||||
because of degradation, especially for the B<Old-age> Attributes.
|
||||
You should then backup more often, run more selftests[1] and prepare
|
||||
the disks replacement.
|
||||
|
||||
B<Act directly>, if a <Pre-Fail> Attribute goes below threshold.
|
||||
Immediately back-up your data and replace your hard disk drive.
|
||||
A failure may be imminent..
|
||||
|
||||
[1] Consult the smartmontools manpages to learn about
|
||||
offline tests and automated selftests with smartd.
|
||||
Only with both activated, the values of the SMART-Attributes
|
||||
reflect the all over state of the device.
|
||||
|
||||
Tutorials and articles about S.M.A.R.T. and smartmontools:
|
||||
http://smartmontools.sourceforge.net/doc.html#tutorials
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
=head1 CALL OPTIONS
|
||||
|
||||
B<none>
|
||||
|
||||
=over 2
|
||||
|
||||
Fetches values if called without arguments:
|
||||
|
||||
E.g.: munin-run smart_hda
|
||||
|
||||
=back
|
||||
|
||||
B<config>
|
||||
|
||||
=over 2
|
||||
|
||||
Prints plugins configuration.
|
||||
|
||||
E.g.: munin-run smart_hda config
|
||||
|
||||
=back
|
||||
|
||||
B<autoconf>
|
||||
|
||||
=over 2
|
||||
|
||||
Tries to find smartctl and outputs value 'yes' for success, 'no' if not.
|
||||
|
||||
It's used by B<munin-node-configure> to see wether autoconfiguration is possible.
|
||||
|
||||
=back
|
||||
|
||||
B<suggest>
|
||||
|
||||
=over 2
|
||||
|
||||
Outputs the list of device names, that it found plugged to the system.
|
||||
|
||||
B<munin-node-configure> use this to build the service links for this wildcard-plugin.
|
||||
|
||||
=back
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Version 2.0
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
(C) 2004-2009 Nicolas Stransky <Nico@stransky.cx>
|
||||
|
||||
(C) 2008 Gabriele Pohl <contact@dipohl.de>
|
||||
Reformated existent documentation to POD-Style, added section Interpretation to the documentation.
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
"""
|
@ -1,145 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (C) 2011 Andreas Thienemann <andreas@bawue.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
=head1 NAME
|
||||
|
||||
smart_raw__ - Munin plugin to retreive raw SMART values from a disk.
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
All machines with a SMART capable disk and smartmontools installed.
|
||||
|
||||
This plugin is very useful if you want to need to monitor a single raw S.M.A.R.T.
|
||||
value reported by a disk. Load Cycle Counts or Pending Sectors come to mind as
|
||||
these are a good indicator of problems with a disk.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
The plugin should be installed as smart_raw_sda_193 which means that the smart value
|
||||
numbered 193 will be read from the disk sda.
|
||||
|
||||
|
||||
Basic configuration for every system is that the plugin needs to be called as root
|
||||
in order to execute smartmontools.
|
||||
|
||||
Add the following to your /etc/munin/plugin-conf.d/smart_raw:
|
||||
|
||||
[smart_raw_sda_193]
|
||||
user root
|
||||
|
||||
=head1 INTERPRETATION
|
||||
|
||||
Smart RAW values are provided as is. You need to undertand what you are monitoring...
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=contrib
|
||||
#%# capabilities=
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
0.0.1
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Andreas Thienemann <andreas@bawue.net>
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv3+
|
||||
|
||||
=cut
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import pprint
|
||||
|
||||
# We are a wildcard plugin, figure out what we are being called for
|
||||
try:
|
||||
disk = sys.argv[0].split('_')[2]
|
||||
value = sys.argv[0].split('_')[3]
|
||||
except IndexError:
|
||||
sys.exit(1)
|
||||
|
||||
def normalize_name(name):
|
||||
name = re.sub("[^a-z0-9A-Z]","_", name)
|
||||
return name
|
||||
|
||||
# Code sniplet from Philipp Keller
|
||||
# http://code.pui.ch/2007/02/19/set-timeout-for-a-shell-command-in-python/
|
||||
def timeout_command(command, timeout):
|
||||
"""call shell-command and either return its output or kill it
|
||||
if it doesn't normally exit within timeout seconds and return None"""
|
||||
import subprocess, datetime, os, time, signal
|
||||
start = datetime.datetime.now()
|
||||
process = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
while process.poll() is None:
|
||||
time.sleep(0.1)
|
||||
now = datetime.datetime.now()
|
||||
if (now - start).seconds> timeout:
|
||||
os.kill(process.pid, signal.SIGKILL)
|
||||
os.waitpid(-1, os.WNOHANG)
|
||||
return None
|
||||
return process.stdout.read()
|
||||
|
||||
def read_smart():
|
||||
"""Read SMART attributes"""
|
||||
out = timeout_command("/usr/sbin/smartctl -A -d ata /dev/%s" % (disk), 2)
|
||||
smart_attribs = dict()
|
||||
for line in out.split('\n')[7:-2]: # Cut away the header and the footer
|
||||
line = line.split()
|
||||
smart_attribs[line[0]] = {
|
||||
'name' : line[1],
|
||||
'label' : normalize_name(line[1]),
|
||||
'raw' : line [-1],
|
||||
}
|
||||
return smart_attribs
|
||||
|
||||
def print_config():
|
||||
"""Return configuration arguments for munin"""
|
||||
attribs = read_smart()
|
||||
print "graph_title S.M.A.R.T raw value %s for drive %s" % (attribs[value]['name'], disk)
|
||||
print "graph_vlabel Raw value"
|
||||
print "graph_info RAW smartctl value"
|
||||
print "graph_category disk"
|
||||
print "graph_args --base 1000 -l 0"
|
||||
|
||||
print "%s.label %s" % (value, attribs[value]['label'])
|
||||
sys.exit(0)
|
||||
|
||||
def fetch():
|
||||
attribs = read_smart()
|
||||
print "%s.value %s" % (value, attribs[value]['raw'])
|
||||
sys.exit(0)
|
||||
|
||||
if "config" in sys.argv[1:]:
|
||||
print_config()
|
||||
elif "autoconf" in sys.argv[1:]:
|
||||
pass
|
||||
elif "suggest" in sys.argv[1:]:
|
||||
pass
|
||||
else:
|
||||
fetch()
|
@ -1,184 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Plugin: sensors_
|
||||
# Author: Carlos Ladeira (caladeira at gmail dot com]
|
||||
# Version: 08.09.13
|
||||
#
|
||||
#
|
||||
# This script handles the output of lm-sensors
|
||||
# like this example:
|
||||
#
|
||||
# it87-isa-0290
|
||||
# Adapter: ISA adapter
|
||||
# VCore 1: +1.49 V (min = +0.00 V, max = +4.08 V)
|
||||
# VCore 2: +2.46 V (min = +0.00 V, max = +4.08 V)
|
||||
# +3.3V: +3.25 V (min = +0.00 V, max = +4.08 V)
|
||||
# +5V: +4.97 V (min = +0.00 V, max = +6.85 V)
|
||||
# +12V: +12.22 V (min = +0.00 V, max = +16.32 V)
|
||||
# -12V: -1.83 V (min = -27.36 V, max = +3.93 V)
|
||||
# -5V: -9.48 V (min = -13.64 V, max = +4.03 V)
|
||||
# Stdby: +4.95 V (min = +0.00 V, max = +6.85 V)
|
||||
# VBat: +3.33 V
|
||||
# fan1: 3375 RPM (min = 0 RPM, div = 8)
|
||||
# fan2: 0 RPM (min = 0 RPM, div = 8)
|
||||
# fan3: 0 RPM (min = 0 RPM, div = 2)
|
||||
# M/B Temp: +39°C (low = -1°C, high = +127°C) sensor = thermistor
|
||||
# CPU Temp: +34°C (low = -1°C, high = +127°C) sensor = thermistor
|
||||
# Temp3: +48°C (low = -1°C, high = +127°C) sensor = thermistor
|
||||
#
|
||||
#
|
||||
# Wildcard-plugin to monitor output of lm sensors.
|
||||
#
|
||||
# Syntax: sensors_<type>[_ignore1[,ignore2[,...]]]
|
||||
#
|
||||
# <type> fans monitor fans speed
|
||||
# voltages monitor system voltages
|
||||
# temperatures monitor system temperatures
|
||||
#
|
||||
# ignore1, ignore2, ... list of sensores to ignore
|
||||
#
|
||||
#
|
||||
# HOW TO SETUP THIS SCRIPT
|
||||
#
|
||||
# 1. Start copying this script to the munin main plugin directory
|
||||
#
|
||||
# sudo cp sensors_ /usr/share/munin/plugins/sensors_
|
||||
#
|
||||
# 2. create links in the user plugin directory with the desired setup
|
||||
# Some examples:
|
||||
#
|
||||
# ln -s /usr/share/munin/plugins/sensors_ /etc/munin/plugins/sensors_fans
|
||||
# ln -s /usr/share/munin/plugins/sensors_ /etc/munin/plugins/sensors_voltages
|
||||
# ln -s /usr/share/munin/plugins/sensors_ /etc/munin/plugins/sensors_temperatures_5V,12V
|
||||
# ln -s /usr/share/munin/plugins/sensors_ /etc/munin/plugins/sensors_temperatures_Temp3
|
||||
#
|
||||
#
|
||||
# Munin (http://munin.projects.linpro.no/)
|
||||
# lm-sensors (http://www.lm-sensors.org/)
|
||||
#
|
||||
# Requirements: * lm-sensors (http://www.lm-sensors.org/)
|
||||
#
|
||||
#
|
||||
# Changelog: v08.09.07 - initial release
|
||||
# v08.09.13 - add ignore parameter list
|
||||
#
|
||||
#
|
||||
#%# family=contrib
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
##### CONSTANTS #####################################################
|
||||
|
||||
DETECTED_SENSORS=$(sensors -U -A | wc -l)
|
||||
GCAT="sensors"
|
||||
|
||||
IGNORE_DELIMITER='_'
|
||||
|
||||
ARGS=$(basename $0 | sed -e 's/^sensors_//g')
|
||||
MODE=$(echo -n $ARGS | cut -d $IGNORE_DELIMITER -f 1)
|
||||
IGNORE=$(echo -n $ARGS | cut -d $IGNORE_DELIMITER -f 2)
|
||||
|
||||
IGNORE_LIST=""
|
||||
if [ -n "$IGNORE" ] ; then
|
||||
if [ "$IGNORE" != "$MODE" ] ; then
|
||||
IGNORE_LIST="$(echo -n $IGNORE | sed -e 's/,/ /g')"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$MODE" in
|
||||
|
||||
voltages)
|
||||
LINE_FILTER=" V"
|
||||
VALUE_FILTER='V'
|
||||
GTITLE="Voltages"
|
||||
GLABEL="Volts"
|
||||
;;
|
||||
|
||||
temperatures)
|
||||
LINE_FILTER="C "
|
||||
VALUE_FILTER='C'
|
||||
GTITLE="Temperatures"
|
||||
GLABEL="Celsius"
|
||||
;;
|
||||
|
||||
fans)
|
||||
LINE_FILTER="RPM"
|
||||
VALUE_FILTER='R'
|
||||
GTITLE="Fans Speed"
|
||||
GLABEL="RPM"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Invalid Option: $MODE"
|
||||
exit 1
|
||||
|
||||
esac
|
||||
|
||||
|
||||
#####################################################################
|
||||
|
||||
if [ "$1" == "autoconf" ]; then
|
||||
|
||||
if [ "$DETECTED_SENSORS" -eq 0 ]; then
|
||||
echo "no"
|
||||
exit 1
|
||||
else
|
||||
echo "yes"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
elif [ "$1" == "suggest" ]; then
|
||||
|
||||
echo "voltages"
|
||||
echo "temperatures"
|
||||
echo "fans"
|
||||
exit 0
|
||||
|
||||
elif [ "$1" == "config" ]; then
|
||||
|
||||
echo "graph_title $GTITLE"
|
||||
echo "graph_vlabel $GLABEL"
|
||||
echo "graph_category $GCAT"
|
||||
echo "graph_args --base 1000 -l 0"
|
||||
echo "graph_scale no"
|
||||
|
||||
sensors | grep "$LINE_FILTER" |
|
||||
|
||||
while read a; do
|
||||
label=$(echo $a | cut -d ':' -f 1 | sed -e 's/[+| |/]//g' -e 's/-/n/' -e 's/\./_/')
|
||||
name=$(echo $a | cut -d ':' -f 1)
|
||||
|
||||
found=0
|
||||
for item in $IGNORE_LIST; do
|
||||
if [ "$item" == "$label" ] ; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $found -eq 0 ] ; then
|
||||
echo $label.label $name
|
||||
fi
|
||||
done
|
||||
|
||||
else
|
||||
|
||||
sensors | grep "$LINE_FILTER" |
|
||||
|
||||
while read a; do
|
||||
label=$(echo $a | cut -d ':' -f 1 | sed -e 's/[+| |/]//g' -e 's/-/n/' -e 's/\./_/')
|
||||
value=$(echo $a | cut -d ':' -f 2 | cut -d $VALUE_FILTER -f 1 | sed -e 's/[+|[:blank:]|°|C]//g')
|
||||
|
||||
found=0
|
||||
for item in $IGNORE_LIST; do
|
||||
if [ "$item" == "$label" ] ; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $found -eq 0 ] ; then
|
||||
echo $label.value $value
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,64 +0,0 @@
|
||||
#!/bin/sh
|
||||
# System statistics for FreeBSD
|
||||
# Author: Gergely Czuczy <phoemix@harmless.hu>
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
sysctl='/sbin/sysctl'
|
||||
|
||||
case $1 in
|
||||
config)
|
||||
cat <<EOF
|
||||
graph_title System Statistics
|
||||
graph_vlabel per second
|
||||
graph_scale no
|
||||
graph_category system
|
||||
graph_args -l 0
|
||||
graph_info FreeBSD systat plugin
|
||||
softint.label Software interrupts
|
||||
softint.type DERIVE
|
||||
softint.min 0
|
||||
hardint.label Hardware interrupts
|
||||
hardint.type DERIVE
|
||||
hardint.min 0
|
||||
syscall.label System calls
|
||||
syscall.type DERIVE
|
||||
syscall.min 0
|
||||
cs.label Context switches
|
||||
cs.type DERIVE
|
||||
cs.min 0
|
||||
forks.label Fork rate
|
||||
forks.type DERIVE
|
||||
forks.min 0
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
autoconf)
|
||||
if [ ! -x ${sysctl} ]; then
|
||||
echo "no (${sysctl} is not executable)"
|
||||
exit 1
|
||||
fi
|
||||
ostype=`uname -s`
|
||||
if [ ${ostype} = "FreeBSD" ]; then
|
||||
echo "yes"
|
||||
exit 0
|
||||
fi
|
||||
echo "no (You're OS is not supported by this plugin)"
|
||||
exit 1
|
||||
;;
|
||||
suggest)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
${sysctl} vm.stats.sys.v_soft vm.stats.sys.v_intr vm.stats.sys.v_syscall vm.stats.sys.v_trap vm.stats.sys.v_swtch \
|
||||
vm.stats.vm.v_forks vm.stats.vm.v_rforks vm.stats.vm.v_vforks| awk '
|
||||
BEGIN {forks=0;}
|
||||
/^vm.stats.sys.v_soft/{print "softint.value",$2}
|
||||
/^vm.stats.sys.v_intr/{print "hardint.value",$2}
|
||||
/^vm.stats.sys.v_syscall/{print "syscall.value",$2}
|
||||
/^vm.stats.sys.v_swtch/{print "cs.value",$2}
|
||||
/^vm.stats.vm.v_[rv]?forks/ {forks+=$2}
|
||||
END {print "forks.value",forks;}
|
||||
'
|
@ -1,140 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
#
|
||||
# Plugin munin affichant la mémoire utilisée, disponible et maximale de la JVM de tomcat.
|
||||
#
|
||||
## Dépendances
|
||||
# xmlstarlet
|
||||
# wget
|
||||
#
|
||||
## Configuration
|
||||
#
|
||||
# Pour pouvoir lire le mot de passe automatiquement, le script doit tourner
|
||||
# sous l'utilisateur tomcat55. Dans /etc/munin/plugin-conf.d/munin-node,
|
||||
# ajouter :
|
||||
#
|
||||
# [tomcat_*]
|
||||
# user tomcat55
|
||||
#
|
||||
# Autres options disponibles :
|
||||
#
|
||||
# env.status_url : URL vers la page « status » en XML du manager
|
||||
# env.http_username : Utilisateur HTTP
|
||||
# env.users_filename : Chemin vers le fichier tomcat-users.xml
|
||||
#
|
||||
##
|
||||
|
||||
TOMCAT_USERS=${users_filename:-'/etc/tomcat5.5/tomcat-users.xml'}
|
||||
USER=${http_username:-'munin'}
|
||||
URLS=( ${status_url:-'http://localhost/manager/status?XML=true https://localhost/manager/status?XML=true http://localhost/manager/status?XML=true'} )
|
||||
|
||||
WARNING=80
|
||||
CRITICAL=90
|
||||
|
||||
#/////////////////////////////////////////////////////////////////////////////////
|
||||
# Affiche un message d'erreur et termine le script en renvoyant le code d'erreur 1
|
||||
#
|
||||
# @param Message à afficher
|
||||
#/////////////////////////////////////////////////////////////////////////////////
|
||||
die(){
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
#////////////////////////////////////////////////////////////////////////////
|
||||
# Récupère le mot de passe de l'utilisateur $1 contenu dans le fichier XML $2
|
||||
#
|
||||
# @param in $1 Nom de l'utilisateur
|
||||
# @param in $2 Fichier XML contenant les utilisateurs Tomcat
|
||||
# @stdout Mot de passe de l'utilisateur
|
||||
#////////////////////////////////////////////////////////////////////////////
|
||||
getPassword(){
|
||||
local PASSWORD=$(xmlstarlet sel -t -m "tomcat-users/user[@username='$1']" -v "@password" "$2" 2> /dev/null)
|
||||
[[ -z $PASSWORD ]] && die "Aucun mot de passe trouvé dans le fichier « $2 » pour le compte « $1 » !"
|
||||
echo $PASSWORD
|
||||
}
|
||||
|
||||
#//////////////////////////////////////////////////////
|
||||
# Récupère la page en XML contenant le statut de la JVM
|
||||
#
|
||||
# @param in $1 Login pour accéder à la page de statut
|
||||
# @param in $2 Mot de passe
|
||||
# @param in $3..$n URL à tester
|
||||
#//////////////////////////////////////////////////////
|
||||
getStatusPage(){
|
||||
local USER="$1"
|
||||
local PASSWORD="$2"
|
||||
while [[ $# -gt 2 ]]; do
|
||||
local STATUS=$(wget -O- -q --no-check-certificate --http-user "$USER" --http-password "$PASSWORD" "$3")
|
||||
[[ -n $STATUS ]] && {
|
||||
echo $STATUS
|
||||
return
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
#///////////////////////////////////////
|
||||
# Affiche la mémoire maximale allouable
|
||||
#
|
||||
# @param in $1 Page de statut de la JVM
|
||||
# @stdout Mémoire maximale allouable
|
||||
#///////////////////////////////////////
|
||||
getMaxMemory(){
|
||||
local MAX_MEM=$(xmlstarlet sel -t -m "status/jvm/memory" -v "@max" <<< "$1" 2> /dev/null)
|
||||
[[ -z $MAX_MEM ]] && die "Impossible de trouver la mémoire maximale allouable !"
|
||||
echo $MAX_MEM
|
||||
}
|
||||
|
||||
#///////////////////////////////////////////////////////////////////////////
|
||||
# Affiche la configuration du plugin
|
||||
#
|
||||
# @param in $1 Mémoire maximale allouable
|
||||
# @param in $2 Pourcentage à utiliser pour définir les « warnings » [0-100]
|
||||
# @param in $3 Pourcentage à utiliser pour définir les « criticals » [0-100]
|
||||
# @stdout Configuration du plugin
|
||||
#///////////////////////////////////////////////////////////////////////////
|
||||
showConfig(){
|
||||
local TMP=$(echo -e {max,total,free}.{'type GAUGE','min 0','draw AREA'}"\n")
|
||||
echo "graph_category Tomcat
|
||||
graph_title Tomcat JVM
|
||||
graph_info Mémoire de la JVM Tomcat
|
||||
graph_vlabel Mémoire
|
||||
$TMP
|
||||
max.label max
|
||||
total.label total
|
||||
free.label free
|
||||
total.warning $(($1 * $2 / 100))
|
||||
total.critical $(($1 * $3 / 100))
|
||||
" | sed -r 's/^\s+//'
|
||||
exit 0
|
||||
}
|
||||
|
||||
#/////////////////////////////////////////////////////////////////////////////////////////
|
||||
# Affiche les données sur la mémoire utilisée, disponible et maximale de la JVM de tomcat.
|
||||
#
|
||||
# @param in $1 Page de statut de la JVM
|
||||
# @stdout Données sur la mémoire utilisée, disponible et maximale de la JVM de tomcat
|
||||
#/////////////////////////////////////////////////////////////////////////////////////////
|
||||
showData(){
|
||||
xmlstarlet sel -t -m "status/jvm/memory" \
|
||||
-o "max.value " -v "@max" -n \
|
||||
-o "total.value " -v "@total" -n \
|
||||
-o "free.value " -v "@free" \
|
||||
<<< "$1" 2> /dev/null
|
||||
}
|
||||
|
||||
# Le fichier $TOMCAT_USERS n'est pas lisible => on quitte
|
||||
[[ ! -r $TOMCAT_USERS ]] && die "Impossible de lire le fichier $TOMCAT_USERS !"
|
||||
|
||||
# On récupère le mot de passe de l'utilisateur $USER
|
||||
PASSWORD=$(getPassword $USER $TOMCAT_USERS)
|
||||
|
||||
# On récupère la page de statut de la JVM de tomcat
|
||||
STATUS_PAGE=$(getStatusPage $USER $PASSWORD $URLS)
|
||||
[[ -z $STATUS_PAGE ]] && die 'Erreur : impossible de récupérer la page de statut de Tomcat !' ;
|
||||
|
||||
# On affiche la configuration du plugin
|
||||
[[ $1 == 'config' ]] && showConfig $(getMaxMemory "$STATUS_PAGE") $WARNING $CRITICAL
|
||||
|
||||
# On affiche les données du plugin
|
||||
showData "$STATUS_PAGE"
|
@ -1,140 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
#
|
||||
# Plugin munin affichant le nombre de threads occupées, disponibles et maximales de la JVM de tomcat.
|
||||
#
|
||||
## Dépendances
|
||||
# xmlstarlet
|
||||
# wget
|
||||
#
|
||||
## Configuration
|
||||
#
|
||||
# Pour pouvoir lire le mot de passe automatiquement, le script doit tourner
|
||||
# sous l'utilisateur tomcat55. Dans /etc/munin/plugin-conf.d/munin-node,
|
||||
# ajouter :
|
||||
#
|
||||
# [tomcat_*]
|
||||
# user tomcat55
|
||||
#
|
||||
# Autres options disponibles :
|
||||
#
|
||||
# env.status_url : URL vers la page « status » en XML du manager
|
||||
# env.http_username : Utilisateur HTTP
|
||||
# env.users_filename : Chemin vers le fichier tomcat-users.xml
|
||||
#
|
||||
##
|
||||
|
||||
TOMCAT_USERS=${users_filename:-'/etc/tomcat5.5/tomcat-users.xml'}
|
||||
USER=${http_username:-'munin'}
|
||||
URLS=( ${status_url:-'http://localhost/manager/status?XML=true https://localhost/manager/status?XML=true http://localhost/manager/status?XML=true'} )
|
||||
|
||||
WARNING=80
|
||||
CRITICAL=90
|
||||
|
||||
#/////////////////////////////////////////////////////////////////////////////////
|
||||
# Affiche un message d'erreur et termine le script en renvoyant le code d'erreur 1
|
||||
#
|
||||
# @param Message à afficher
|
||||
#/////////////////////////////////////////////////////////////////////////////////
|
||||
die(){
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
#////////////////////////////////////////////////////////////////////////////
|
||||
# Récupère le mot de passe de l'utilisateur $1 contenu dans le fichier XML $2
|
||||
#
|
||||
# @param in $1 Nom de l'utilisateur
|
||||
# @param in $2 Fichier XML contenant les utilisateurs Tomcat
|
||||
# @stdout Mot de passe de l'utilisateur
|
||||
#////////////////////////////////////////////////////////////////////////////
|
||||
getPassword(){
|
||||
local PASSWORD=$(xmlstarlet sel -t -m "tomcat-users/user[@username='$1']" -v "@password" "$2" 2> /dev/null)
|
||||
[[ -z $PASSWORD ]] && die "Aucun mot de passe trouvé dans le fichier « $2 » pour le compte « $1 » !"
|
||||
echo $PASSWORD
|
||||
}
|
||||
|
||||
#//////////////////////////////////////////////////////
|
||||
# Récupère la page en XML contenant le statut de la JVM
|
||||
#
|
||||
# @param in $1 Login pour accéder à la page de statut
|
||||
# @param in $2 Mot de passe
|
||||
# @param in $3..$n URL à tester
|
||||
#//////////////////////////////////////////////////////
|
||||
getStatusPage(){
|
||||
local USER="$1"
|
||||
local PASSWORD="$2"
|
||||
while [[ $# -gt 2 ]]; do
|
||||
local STATUS=$(wget -O- -q --no-check-certificate --http-user "$USER" --http-password "$PASSWORD" "$3")
|
||||
[[ -n $STATUS ]] && {
|
||||
echo $STATUS
|
||||
return
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
#///////////////////////////////////////
|
||||
# Affiche le nombre maximal de threads
|
||||
#
|
||||
# @param in $1 Page de statut de la JVM
|
||||
# @stdout Nombre maximal de threads
|
||||
#///////////////////////////////////////
|
||||
getMaxThreads(){
|
||||
local MAX_THREADS=$(xmlstarlet sel -t -m "status/connector/threadInfo" -v "@maxThreads" <<< "$1" 2> /dev/null)
|
||||
[[ -z $MAX_THREADS ]] && die "Impossible de trouver le nombre maximal de threads !"
|
||||
echo $MAX_THREADS
|
||||
}
|
||||
|
||||
#///////////////////////////////////////////////////////////////////////////
|
||||
# Affiche la configuration du plugin
|
||||
#
|
||||
# @param in $1 Nombre maximal de threads
|
||||
# @param in $2 Pourcentage à utiliser pour définir les « warnings » [0-100]
|
||||
# @param in $3 Pourcentage à utiliser pour définir les « criticals » [0-100]
|
||||
# @stdout Configuration du plugin
|
||||
#///////////////////////////////////////////////////////////////////////////
|
||||
showConfig(){
|
||||
local TMP=$(echo -e {maxThreads,currentThreadCount,currentThreadsBusy}.{'type GAUGE','min 0','draw AREA'}"\n")
|
||||
echo "graph_category Tomcat
|
||||
graph_title Tomcat Threads
|
||||
graph_info nombre de threads occupées, disponibles et maximales de la JVM de tomcat
|
||||
graph_vlabel Threads
|
||||
$TMP
|
||||
maxThreads.label maxThreads
|
||||
currentThreadCount.label currentThreadCount
|
||||
currentThreadsBusy.label currentThreadsBusy
|
||||
currentThreadCount.warning $(($1 * $2 / 100))
|
||||
currentThreadCount.critical $(($1 * $3 / 100))
|
||||
" | sed -r 's/^\s+//'
|
||||
exit 0
|
||||
}
|
||||
|
||||
#////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
# Affiche les données sur le nombre de threads occupées, disponibles et maximales de la JVM de tomcat
|
||||
#
|
||||
# @param in $1 Page de statut de la JVM
|
||||
# @stdout Données sur le nombre de threads occupées, disponibles et maximales de la JVM de tomcat
|
||||
#////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
showData(){
|
||||
xmlstarlet sel -t -m "status/connector/threadInfo" \
|
||||
-o "currentThreadCount.value " -v "@currentThreadCount" -n \
|
||||
-o "currentThreadsBusy.value " -v "@currentThreadsBusy" -n \
|
||||
-o "maxThreads.value " -v "@maxThreads" \
|
||||
<<< "$1" #2> /dev/null
|
||||
}
|
||||
|
||||
# Le fichier $TOMCAT_USERS n'est pas lisible => on quitte
|
||||
[[ ! -r $TOMCAT_USERS ]] && die "Impossible de lire le fichier $TOMCAT_USERS !"
|
||||
|
||||
# On récupère le mot de passe de l'utilisateur $USER
|
||||
PASSWORD=$(getPassword $USER $TOMCAT_USERS)
|
||||
|
||||
# On récupère la page de statut de la JVM de tomcat
|
||||
STATUS_PAGE=$(getStatusPage $USER $PASSWORD $URLS)
|
||||
[[ -z $STATUS_PAGE ]] && die 'Erreur : impossible de récupérer la page de statut de Tomcat !' ;
|
||||
|
||||
# On affiche la configuration du plugin
|
||||
[[ $1 == 'config' ]] && showConfig $(getMaxThreads "$STATUS_PAGE") $WARNING $CRITICAL
|
||||
|
||||
# On affiche les données du plugin
|
||||
showData "$STATUS_PAGE"
|
@ -1,283 +0,0 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# Plugin to monitor the Tomcat servers.
|
||||
#
|
||||
# Original Author: Rune Nordboe Skillingstad <runesk@linpro.no>
|
||||
# Rewrite: laxis <laxis@magex.hu> 2008.05
|
||||
#
|
||||
# Requirements:
|
||||
# - Needs access to http://<user>:<password>@localhost:8080/manager/status?XML=true (or modify the
|
||||
# address for another host). A munin-user in $CATALINA_HOME/conf/tomcat-users.xml
|
||||
# should be set up for this to work.
|
||||
# - libxml-ruby
|
||||
#
|
||||
# Install:
|
||||
# - copy script to /etc/munin
|
||||
# - cd /etc/munin
|
||||
# - ./tomcat install
|
||||
#
|
||||
# Tip: To see if it's already set up correctly, just run this plugin
|
||||
# with the parameter "autoconf". If you get a "yes", everything should
|
||||
# work like a charm already.
|
||||
#
|
||||
# tomcat-users.xml example:
|
||||
# <user username="munin" password="<set this>" roles="standard,manager"/>
|
||||
#
|
||||
# Parameters supported:
|
||||
#
|
||||
# config
|
||||
# autoconf
|
||||
# install
|
||||
#
|
||||
# Configurable variables
|
||||
#
|
||||
# host - Destination host
|
||||
# port - HTTP port numbers
|
||||
# timeout - Connection timeout
|
||||
# request - Override default status-url
|
||||
# user - Manager username
|
||||
# password - Manager password
|
||||
# connector - Connector to query, defaults to "http-".$PORT
|
||||
#
|
||||
# Sample config:
|
||||
# [tomcat_*]
|
||||
# env.host 127.0.0.1
|
||||
# env.port 8080
|
||||
# env.request /manager/status?XML=true
|
||||
# env.user munin
|
||||
# env.password pass
|
||||
# env.timeout 30
|
||||
# env.connector jk-8009
|
||||
#
|
||||
# Magic markers:
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
|
||||
require 'net/http'
|
||||
require 'xml/libxml'
|
||||
|
||||
@host = ENV.member?('host') ? ENV['host']: "127.0.0.1"
|
||||
@port = ENV.member?('port') ? ENV['port']: 8080
|
||||
@request = ENV.member?('request') ? ENV['request']: "/manager/status?XML=true"
|
||||
@user = ENV.member?('user') ? ENV['user']: "munin"
|
||||
@password = ENV.member?('password') ? ENV['password']: "munin"
|
||||
@timeout = ENV.member?('timeout') ? ENV['timeout']: 30
|
||||
@connector = ENV.member?('connector') ? ENV['connector']: "http-#{@port}";
|
||||
|
||||
# hash
|
||||
w = {
|
||||
"jvmMemory" => { "max" => "U",
|
||||
"total" => "U",
|
||||
"used" => "U" },
|
||||
"threadInfo" => { "maxThreads" => "U",
|
||||
"currentThreadCount" => "U",
|
||||
"currentThreadsBusy" => "U" },
|
||||
"requestMaxTime" => { "maxTime" => "U" },
|
||||
"requestTime" => { "avgTime" => "U" },
|
||||
"requestCount" => { "requestCount" => "U",
|
||||
"errorCount" => "U" },
|
||||
"requestBytes" => { "bytesReceived" => "U",
|
||||
"bytesSent" => "U" }
|
||||
}
|
||||
|
||||
# http request
|
||||
def getstat()
|
||||
Net::HTTP.start(@host, @port) do |http|
|
||||
http.open_timeout = @timeout
|
||||
req = Net::HTTP::Get.new(@request)
|
||||
req.basic_auth @user, @password
|
||||
response = http.request(req)
|
||||
response.value()
|
||||
return response.body
|
||||
end rescue begin
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def autoconf()
|
||||
begin
|
||||
if getstat()
|
||||
puts "yes"
|
||||
return 0
|
||||
end
|
||||
rescue
|
||||
puts "no (#{$!})"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
if ARGV[0] == "autoconf"
|
||||
exit autoconf()
|
||||
end
|
||||
|
||||
if ARGV[0] == "install"
|
||||
exit if autoconf() != 0
|
||||
Dir["plugins/tomcat*"].each { |f|
|
||||
print "removing #{f}\n"
|
||||
File.unlink f
|
||||
}
|
||||
w.each { |k, v|
|
||||
print "installing plugins/tomcat_#{k}\n"
|
||||
File.symlink "../tomcat", "plugins/tomcat_#{k}" if ! FileTest.symlink? "plugins/tomcat_#{k}"
|
||||
}
|
||||
exit
|
||||
end
|
||||
|
||||
# open stderr
|
||||
e = IO.new(2, "w")
|
||||
|
||||
mode = $0.gsub /.*\/tomcat_/, ""
|
||||
if mode =~ /tomcat/ then
|
||||
e.puts "Invalid mode"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# munin config request
|
||||
if ARGV[0] == "config"
|
||||
puts "graph_title tomcat_#{mode}"
|
||||
puts "graph_args -l 0 --base 1000"
|
||||
#print "graph_order "
|
||||
#w[mode].each { |k, v|
|
||||
#print "#{k} "
|
||||
#}
|
||||
#puts
|
||||
case mode
|
||||
when "jvmMemory"
|
||||
puts "graph_category tomcat"
|
||||
puts "graph_vlabel bytes"
|
||||
puts "graph_order max total used"
|
||||
w[mode].each { |k, v|
|
||||
puts "#{k}.label #{k}"
|
||||
puts "#{k}.type GAUGE"
|
||||
puts "#{k}.min 0"
|
||||
puts "#{k}.draw AREA"
|
||||
}
|
||||
when "requestCount"
|
||||
puts "graph_category tomcat"
|
||||
puts "graph_order requestCount errorCount"
|
||||
puts "graph_vlabel Request / sec"
|
||||
w[mode].each { |k, v|
|
||||
puts "#{k}.label #{k}"
|
||||
puts "#{k}.type COUNTER"
|
||||
puts "#{k}.min 0"
|
||||
puts "#{k}.draw AREA" if k == "requestCount"
|
||||
puts "#{k}.draw LINE2" if k != "requestCount"
|
||||
}
|
||||
when "requestBytes"
|
||||
puts "graph_category tomcat"
|
||||
puts "graph_vlabel bytes in (-) / out (+) per ${graph_period}"
|
||||
w[mode].each { |k, v|
|
||||
puts "#{k}.label #{k}"
|
||||
puts "#{k}.type DERIVE"
|
||||
puts "#{k}.min 0"
|
||||
puts "#{k}.graph no" if k == "bytesReceived"
|
||||
puts "#{k}.negative bytesReceived" if k == "bytesSent"
|
||||
|
||||
}
|
||||
when "requestMaxTime"
|
||||
puts "graph_category tomcat"
|
||||
puts "graph_vlabel sec"
|
||||
w[mode].each { |k, v|
|
||||
puts "#{k}.label #{k}"
|
||||
puts "#{k}.type GAUGE"
|
||||
puts "#{k}.min 0"
|
||||
puts "#{k}.draw LINE2"
|
||||
}
|
||||
when "requestTime"
|
||||
puts "graph_category tomcat"
|
||||
puts "graph_vlabel Average RequestTime (sec) / Request"
|
||||
w[mode].each { |k, v|
|
||||
puts "#{k}.label #{k}"
|
||||
puts "#{k}.type GAUGE"
|
||||
puts "#{k}.min 0"
|
||||
puts "#{k}.draw LINE2"
|
||||
}
|
||||
when "threadInfo"
|
||||
puts "graph_category tomcat"
|
||||
puts "graph_order maxThreads currentThreadCount currentThreadsBusy"
|
||||
w[mode].each { |k, v|
|
||||
puts "#{k}.label #{k}"
|
||||
puts "#{k}.type GAUGE"
|
||||
puts "#{k}.min 0"
|
||||
puts "#{k}.draw AREA"
|
||||
}
|
||||
end
|
||||
exit 0
|
||||
end
|
||||
|
||||
|
||||
# XML parsolasa
|
||||
begin
|
||||
parser = XML::Parser.string(getstat())
|
||||
doc = parser.parse
|
||||
end rescue begin
|
||||
e.puts "Parse error"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# root element kivalasztasa
|
||||
root = doc.root
|
||||
if root.name != "status"
|
||||
e.puts "Invalid XML"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# copy jvm memory datas to hash
|
||||
node = doc.find('//status/jvm/memory').first
|
||||
w["jvmMemory"]["used"] = node.property("total").to_i - node.property("free").to_i
|
||||
w["jvmMemory"]["total"] = node.property("total")
|
||||
w["jvmMemory"]["max"] = node.property("max")
|
||||
|
||||
# copy connector datas to hash
|
||||
doc.find('//status/connector').each do |node|
|
||||
if node.property("name") == @connector
|
||||
node.each do |child|
|
||||
if child.name == "threadInfo"
|
||||
w["threadInfo"]["maxThreads"] = child.property("maxThreads")
|
||||
w["threadInfo"]["currentThreadCount"] = child.property("currentThreadCount")
|
||||
w["threadInfo"]["currentThreadsBusy"] = child.property("currentThreadsBusy")
|
||||
end
|
||||
if child.name == "requestInfo"
|
||||
w["requestMaxTime"]["maxTime"] = child.property("maxTime")
|
||||
w["requestTime"]["avgTime"] = sprintf "%.2f", (child.property("processingTime").to_f / child.property("requestCount").to_f / 1000)
|
||||
w["requestCount"]["requestCount"] = child.property("requestCount")
|
||||
w["requestCount"]["errorCount"] = child.property("errorCount")
|
||||
w["requestBytes"]["bytesReceived"] = child.property("bytesReceived")
|
||||
w["requestBytes"]["bytesSent"] = child.property("bytesSent")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# print result
|
||||
w[mode].each do |k, v|
|
||||
printf "#{k}.value %s\n", v
|
||||
end
|
||||
|
||||
# XML Output:
|
||||
#<?xml version="1.0" encoding="utf-8"?>
|
||||
#<?xml-stylesheet type="text/xsl" href="/manager/xform.xsl" ?>
|
||||
#<status>
|
||||
# <jvm>
|
||||
# <memory free='110552760' total='257425408' max='1034027008'/>
|
||||
# </jvm>
|
||||
# <connector name='http-8080'>
|
||||
# <threadInfo maxThreads="40" currentThreadCount="1" currentThreadsBusy="1" />
|
||||
# <requestInfo maxTime="14" processingTime="2619" requestCount="1911" errorCount="5" bytesReceived="0" bytesSent="3294996" />
|
||||
# <workers>
|
||||
# <worker stage="S" requestProcessingTime="0" requestBytesSent="0" requestBytesReceived="0" remoteAddr="127.0.0.1" virtualHost="localhost" method="GET" currentUri="/manager/status" currentQueryString="XML=true" protocol="HTTP/1.0" />
|
||||
# </workers>
|
||||
# </connector>
|
||||
# <connector name='jk-8009'>
|
||||
# <threadInfo maxThreads="200" currentThreadCount="8" currentThreadsBusy="6" />
|
||||
# <requestInfo maxTime="36961" processingTime="273750" requestCount="5485" errorCount="43" bytesReceived="0" bytesSent="57138822" />
|
||||
# <workers>
|
||||
# <worker stage="K" requestProcessingTime="22683456" requestBytesSent="0" requestBytesReceived="0" remoteAddr="86.101.240.226" virtualHost="?" method="?" currentUri="?" currentQueryString="?" protocol="?" />
|
||||
# <worker stage="K" requestProcessingTime="35807" requestBytesSent="0" requestBytesReceived="0" remoteAddr="217.20.130.27" virtualHost="?" method="?" currentUri="?" currentQueryString="?" protocol="?" />
|
||||
# <worker stage="K" requestProcessingTime="32247045" requestBytesSent="0" requestBytesReceived="0" remoteAddr="89.147.76.234" virtualHost="?" method="?" currentUri="?" currentQueryString="?" protocol="?" />
|
||||
# <worker stage="K" requestProcessingTime="95860" requestBytesSent="0" requestBytesReceived="0" remoteAddr="217.20.130.27" virtualHost="?" method="?" currentUri="?" currentQueryString="?" protocol="?" />
|
||||
# <worker stage="K" requestProcessingTime="155940" requestBytesSent="0" requestBytesReceived="0" remoteAddr="217.20.130.27" virtualHost="?" method="?" currentUri="?" currentQueryString="?" protocol="?" />
|
||||
# </workers>
|
||||
# </connector>
|
||||
#</status>
|
@ -1,184 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
'''
|
||||
Wildcard plugin to monitor Apache Tomcat connectors and/or JBoss' JVM.
|
||||
|
||||
To use this plugin:
|
||||
1. Set site, username and password variables before you do anything else.
|
||||
2. Run plugin with suggest argument to get all the available options.
|
||||
3. Copy plugin to munin plugins folder and make it executable.
|
||||
4. Create symbolic links based on output from step 2. Examples:
|
||||
tomcat_jvm - monitor JVM usage
|
||||
tomcat_ajp-127.0.0.1-8009 - monitor ajp connector
|
||||
tomcat_http-127.0.0.1-8080 - monitor http connector
|
||||
5. Check links by running them.
|
||||
6. Restart munin-node.
|
||||
7. Enjoy graphs.
|
||||
|
||||
Munin's muni-node-configure can be used to do steps 2, 3 and 4 for you.
|
||||
|
||||
Example of using munin-node configuration to configure the plugin:
|
||||
|
||||
[tomcat_jvm]
|
||||
env.site http://127.0.0.1:8080/status?XML=true
|
||||
env.username admin
|
||||
env.password admin
|
||||
env.url_timeout 5
|
||||
timeout 10
|
||||
|
||||
url_timeout - timeout for urllib2
|
||||
timeout - plugin timeout
|
||||
|
||||
Plugin must return before timeout value runs out, otherwise bye, bye
|
||||
graphs.
|
||||
|
||||
Magic markers
|
||||
#%# capabilities=autoconf suggest
|
||||
#%# family=auto
|
||||
'''
|
||||
|
||||
import urllib2
|
||||
import base64
|
||||
import xml.dom.minidom
|
||||
import sys, os, re
|
||||
|
||||
# Configure me ...
|
||||
site = 'http://127.0.0.1:8080/status?XML=true'
|
||||
url_timeout = 5
|
||||
username = 'admin'
|
||||
password = 'admin'
|
||||
|
||||
# Or do it with the environment variables in munin-node configuration.
|
||||
if os.environ.has_key('site'):
|
||||
site = os.environ['site']
|
||||
|
||||
if os.environ.has_key('url_timeout'):
|
||||
url_timeout = os.environ['url_timeout']
|
||||
|
||||
if os.environ.has_key('username'):
|
||||
username = os.environ['username']
|
||||
|
||||
if os.environ.has_key('password'):
|
||||
password = os.environ['password']
|
||||
|
||||
# Timeout for urlopen.
|
||||
required_version = (2, 6)
|
||||
current_version = sys.version_info[:2]
|
||||
|
||||
connector_attrs = (
|
||||
'maxThreads',
|
||||
'minSpareThreads',
|
||||
'maxSpareThreads',
|
||||
'currentThreadCount',
|
||||
'currentThreadBusy'
|
||||
)
|
||||
|
||||
jvm_attrs = (
|
||||
'free',
|
||||
'total',
|
||||
'max'
|
||||
)
|
||||
|
||||
ctx = sys.argv[0].rstrip('.py').split('_')[1]
|
||||
|
||||
def site_auth():
|
||||
# Prepare base64 encoded string
|
||||
enc_string = base64.encodestring('%s:%s' % (username, password))
|
||||
|
||||
# Prepare request and add headers
|
||||
request = urllib2.Request(url=site, headers={"Authorization": "Basic %s" % enc_string})
|
||||
try:
|
||||
if current_version >= required_version:
|
||||
return (0, urllib2.urlopen(request, timeout=url_timeout).read())
|
||||
else:
|
||||
import socket
|
||||
socket.setdefaulttimeout(url_timeout)
|
||||
return (0, urllib2.urlopen(request).read())
|
||||
except:
|
||||
return (-1, "Failed to access %s" % site)
|
||||
|
||||
def jvm_data(data):
|
||||
document = data.documentElement
|
||||
for sub_document in document.childNodes:
|
||||
if sub_document.nodeName == 'jvm':
|
||||
node = sub_document.firstChild
|
||||
for attr in jvm_attrs:
|
||||
print "%s.value %s" % (attr, int(node.getAttribute(attr)))
|
||||
|
||||
def connector_data(data, connector_name):
|
||||
document = data.documentElement
|
||||
for sub_document in document.childNodes:
|
||||
if sub_document.nodeName == 'connector' and sub_document.getAttribute('name') == connector_name:
|
||||
node = sub_document.firstChild
|
||||
for attr in connector_attrs:
|
||||
try:
|
||||
print "%s.value %s" % (attr, int(node.getAttribute(attr)))
|
||||
except:
|
||||
pass
|
||||
|
||||
def suggest(data):
|
||||
document = data.documentElement
|
||||
for sub_document in document.childNodes:
|
||||
if sub_document.nodeName == 'jvm':
|
||||
print "jvm"
|
||||
elif sub_document.nodeName == 'connector':
|
||||
print sub_document.getAttribute('name')
|
||||
else:
|
||||
pass
|
||||
|
||||
def configure():
|
||||
print "graph_title Tomcat status - %s" % ctx
|
||||
print "graph_category tomcat"
|
||||
if ctx == 'jvm':
|
||||
print "graph_args --base 1024 -l 0"
|
||||
print "graph_scale yes"
|
||||
print "graph_vlabel JVM in bytes"
|
||||
print "graph_info This graph shows JVM usage of Tomcat."
|
||||
for attr in jvm_attrs:
|
||||
print "%s.label %s" % (attr, attr)
|
||||
print "%s.type GAUGE" % (attr)
|
||||
print "%s.min 0" % (attr)
|
||||
print "%s.draw LINE1" % (attr)
|
||||
print "%s.info %s %s in bytes" % (attr, ctx, attr)
|
||||
else:
|
||||
print "graph_args --base 1000 -l 0"
|
||||
print "graph_scale no"
|
||||
print "graph_vlabel Connector threads"
|
||||
print "graph_info This graph shows connector threads for %s" % ctx
|
||||
for attr in connector_attrs:
|
||||
print "%s.label %s" % (attr, attr)
|
||||
print "%s.type GAUGE" % (attr)
|
||||
print "%s.min 0" % (attr)
|
||||
print "%s.draw LINE1" % (attr)
|
||||
print "%s.info %s %s count" % (attr, ctx, attr)
|
||||
|
||||
if __name__ == "__main__":
|
||||
status, data = site_auth()
|
||||
if len(sys.argv) == 2 and sys.argv[1] == 'config':
|
||||
configure()
|
||||
sys.exit(0)
|
||||
|
||||
elif len(sys.argv) == 2 and sys.argv[1] == 'suggest':
|
||||
suggest(xml.dom.minidom.parseString(data))
|
||||
sys.exit(0)
|
||||
|
||||
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
|
||||
if status == 0:
|
||||
print "yes"
|
||||
else:
|
||||
print "no (%s)" % data
|
||||
sys.exit(0)
|
||||
|
||||
else:
|
||||
if ctx == 'jvm':
|
||||
if status == -1:
|
||||
for attr in jvm_attrs:
|
||||
print "%s.value 0" % (attr)
|
||||
else:
|
||||
jvm_data(xml.dom.minidom.parseString(data))
|
||||
else:
|
||||
if status == -1:
|
||||
for attr in connector_attrs:
|
||||
print "%s.value 0" % (attr)
|
||||
else:
|
||||
connector_data(xml.dom.minidom.parseString(data), ctx)
|
@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env groovy
|
||||
/*
|
||||
* Reports tomcat thread status from the tomcat manager application
|
||||
*
|
||||
* Stian B. Lindhom <stian@lindhom.no> 2010
|
||||
*/
|
||||
|
||||
def username = ''
|
||||
def password = ''
|
||||
def addr = 'http://localhost:8080/manager/status?XML=true'
|
||||
def connector = 'http-8080'
|
||||
|
||||
def authString = (username + ":" + password).getBytes().encodeBase64()
|
||||
def conn = addr.toURL().openConnection()
|
||||
|
||||
def maxthreads
|
||||
def threadsBusy
|
||||
def threadCount
|
||||
conn.setRequestProperty("Authorization", "Basic ${authString}")
|
||||
if (conn.responseCode == 200) {
|
||||
def doc = new XmlParser().parseText(conn.content.text)
|
||||
httpConnector = doc.connector.findAll{ it.'@name'.contains(connector) }[0]
|
||||
maxthreads = Integer.parseInt(httpConnector.threadInfo.'@maxThreads'.text())
|
||||
threadsBusy = Integer.parseInt(httpConnector.threadInfo.'@currentThreadsBusy'.text())
|
||||
threadCount = Integer.parseInt(httpConnector.threadInfo.'@currentThreadCount'.text())
|
||||
}
|
||||
|
||||
if (args && args[0] == 'config') {
|
||||
warningThreshold = (Integer) (maxthreads - (maxthreads* 0.2))
|
||||
criticalThreshold = (Integer) (maxthreads - (maxthreads * 0.05))
|
||||
|
||||
println """graph_category Tomcat
|
||||
graph_title Tomcat threads
|
||||
graph_info The number of busy threads describes how many HTTP requests are being processed at the moment
|
||||
graph_vlabel Threads
|
||||
currentThreadCount.label currentThreadCount
|
||||
currentThreadsBusy.label currentThreadsBusy
|
||||
maxThreads.label maxThreads
|
||||
currentThreadCount.warning ${warningThreshold}
|
||||
currentThreadCount.critical ${criticalThreshold}"""
|
||||
return;
|
||||
}
|
||||
|
||||
println """currentThreadCount.value ${threadCount}
|
||||
currentThreadsBusy.value ${threadsBusy}
|
||||
maxThreads.value ${maxthreads}"""
|
Loading…
Reference in New Issue
Block a user