#!/usr/bin/perl -w # # Plugin to monitor harddrive temperatures through SMART. # # client-conf.d/-options: # # smartctl -- path to smartctl executable # drives -- List drives to monitor. E.g. "env.drives hda hdc". # type_$dev -- device type for one drive, e.g. "env.type_sda 3ware,0" # args_$dev -- additional arguments to smartctl for one drive, # e.g. "env.args_hda -v 194,10xCelsius" # Use this to make the plugin use the --all or -a option # if your disk will not return it's temperature when # only the -A option is used. # # Note for users of RAID controllers (smartmontools currently only # supports 3ware): you can specify the drives attached to your RAID # controller(s) as raiddev_num (e.g. sda_0). Then you must specify the # type like this: type_sda_0 3ware,0. # # $Log$ # Revision 1.1.2.5 2005/03/03 10:22:25 lupe # Add feature to specify additional arguments to smartctl # # Revision 1.1.2.4 2005/02/17 10:59:33 lupe # Support more than one drive on RAID controllers. Explain how to configure # them. # # Revision 1.1.2.3 2005/01/29 22:14:36 jimmyo # Make the plugin check all rdsks. # # Revision 1.1.2.2 2005/01/26 09:34:37 jimmyo # Added license note. # # Revision 1.1.2.1 2005/01/25 21:00:05 jimmyo # Added plugin generic/hddtemp_smartctl, made by Lupe Christoph. Made it the default hddtemp plugin. # # Revision 1.1 2004/11/10 16:11:27 jimmyo # Added new plugin linux/hddtemp_smartctl, made by Peter Gervai (SF#1032727). # # Revision 1.0 2004/09/22 # New plugin: Peter Gervai # # #%# family=auto #%# capabilities=autoconf # # Copyright (c) 2005, Lutz Peter Christoph # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # * The name and aliases of Lutz Peter Christoph ("Lupe Christoph", # "Lutz Christoph") may not be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use strict; my $smartctl = exists $ENV{smartctl} ? $ENV{smartctl} : undef; # If the envvar is not set, look for smartctl # first, try $PATH $smartctl = `which smartctl` unless $smartctl; chomp $smartctl; $smartctl = undef unless -x $smartctl; # Still not found? Check obvious places my @dirs = qw(/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin); until ($smartctl or @dirs == 0) { my $dir = shift @dirs; my $path = $dir.'/smartctl'; $smartctl = $path if -x $path; } $ENV{LANG} = 'C'; $ENV{LC_ALL} = 'C'; my @drives; # Try to get a default set of drives if ($^O eq 'darwin') { opendir(DEV, '/dev'); @drives = grep /^disk[0-9]+$/, readdir DEV; closedir(DEV); } elsif ($^O eq 'freebsd') { opendir(DEV, '/dev'); @drives = grep /^ad|da[0-9]+$/, readdir DEV; closedir(DEV); } elsif ($^O eq 'linux') { # On Linux, we know how to enumerate ide drives. # SCSI is not as easy if (-d '/dev') { opendir(IDE, '/dev'); @drives = grep /^sd[a-z]$/, readdir IDE; closedir(IDE); } } elsif (($^O eq 'netbsd') or ($^O eq 'openbsd')) { opendir(DEV, '/dev'); @drives = grep /^wd|sd[0-9]+c$/, readdir DEV; closedir(DEV); } elsif ($^O eq 'solaris') { @drives = map { s@.*/@@ ; $_ } glob '/dev/rdsk/c*t*d*s2'; } @drives = split ' ', $ENV{drives} if exists $ENV{drives}; # Sort list of drives @drives = sort @drives; if (defined $ARGV[0]) { if ($ARGV[0] eq 'autoconf') { if ($smartctl and -x $smartctl) { if (@drives) { print "yes\n"; exit 0; } else { print "no (no drives known)\n"; exit 1; } } else { print "no (smartctl not found)\n"; exit 1; } } elsif ($ARGV[0] eq 'config') { print "graph_title HDD temperature\n"; print "graph_args --base 1000 -l 0\n"; print "graph_vlabel temp in �C\n"; print "graph_category sensors\n"; print "graph_info This graph shows the temperature in degrees Celsius of the hard drives in the machine.\n"; print "$_.label $_\n" foreach @drives; exit 0; } } foreach (@drives) { my $dev; $dev = $_ =~ /(.*)(?:_\d+)/ ? $1 : $_; my $cmd = $smartctl.' -A '; $cmd .= $ENV{'args_'.$_}.' ' if exists $ENV{'args_'.$_}; $cmd .= '-d '.$ENV{'type_'.$_}.' ' if exists $ENV{'type_'.$_}; if ($^O eq 'solaris') { $cmd .= "/dev/rdsk/$dev"; } else { $cmd .= "/dev/$dev"; } my $output = `$cmd`; if ($output =~ /Current Drive Temperature:\s*(\d+)/) { print "$_.value $1\n"; } elsif ($output =~ /^(194 Temperature_Celsius.*)/m) { my @F = split ' ', $1; print "$_.value $F[9]\n"; } }