mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-24 18:07:20 +00:00
remove plugins existing in main munin repository
This commit is contained in:
parent
331d5a43dc
commit
accf47f9a0
13 changed files with 0 additions and 4157 deletions
|
@ -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()
|
Loading…
Add table
Add a link
Reference in a new issue