initial
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.swp
|
||||
381
sensors_
Executable file
381
sensors_
Executable file
@@ -0,0 +1,381 @@
|
||||
#!/usr/bin/perl -w
|
||||
# -*- perl -*-
|
||||
=head1 NAME
|
||||
|
||||
sensors_ - Wildcard-plugin to monitor information from temperature,
|
||||
voltage, and fan speed sensors.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
The possible wildcard values are the follwing: fan, temp, volt. So you
|
||||
would create symlinks to this plugin called sensors_fan, sensors_temp,
|
||||
and sensors_volt.
|
||||
|
||||
The plugins needs the following components configured:
|
||||
|
||||
=over
|
||||
|
||||
=item i2c and lm_sensors modules installed and loaded.
|
||||
|
||||
=item sensors program installed and in path.
|
||||
|
||||
=back
|
||||
|
||||
Note: Sensor names are read from the output of the sensors program.
|
||||
Change them in /etc/sensors.conf if you don't like them.
|
||||
|
||||
[sensors_*]
|
||||
env.sensors - Override default sensors program path
|
||||
env.ignore_temp<n> - Temperature <n> will not be plotted
|
||||
env.ignore_fan<n> - Fan <n> will not be plotted
|
||||
env.ignore_volt<n> - Voltage <n> will not be plotted
|
||||
env.fan_warn_percent - Percentage over mininum for warning
|
||||
env.volt_warn_percent - Percentage over mininum/under maximum for warning
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Unknown author
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
$ENV{'LANG'} = "C"; # Force parsable output from sensors.
|
||||
$ENV{'LC_ALL'} = "C"; # Force parsable output from sensors.
|
||||
my $SENSORS = $ENV{'sensors'} || 'sensors';
|
||||
|
||||
# Example outputs from sensors & matching regex parts:
|
||||
|
||||
# Fan output example from sensors:
|
||||
# --------------------------------
|
||||
# Case Fan: 1268 RPM (min = 3750 RPM, div = 8) ALARM
|
||||
# CPU Fan: 0 RPM (min = 1171 RPM, div = 128) ALARM
|
||||
# Aux Fan: 0 RPM (min = 753 RPM, div = 128) ALARM
|
||||
# fan4: 3375 RPM (min = 774 RPM, div = 8)
|
||||
# fan5: 0 RPM (min = 1054 RPM, div = 128) ALARM
|
||||
#
|
||||
# ^^^^ ^^^^ ^^^^
|
||||
# $1 $2 $3
|
||||
#
|
||||
# --------------------------------
|
||||
#
|
||||
# Temperature output example from sensors:
|
||||
# * Note that the degree character is replaced by a space, as we are running
|
||||
# with LC_ALL=C and LANG=C.
|
||||
# ---------------------------------------
|
||||
# Sys Temp: +41.0 C (high = -128.0 C, hyst = +24.0 C) ALARM sensor = thermistor
|
||||
# CPU Temp: +40.5 C (high = +80.0 C, hyst = +75.0 C) sensor = thermistor
|
||||
# AUX Temp: +39.0 C (high = +80.0 C, hyst = +75.0 C) sensor = thermistor
|
||||
#
|
||||
# ^^^^^^^^ ^^ ^^ ^^
|
||||
# $1 $2 $3 $4
|
||||
#
|
||||
# ---------------------------------------
|
||||
#
|
||||
# Voltage output example from sensors:
|
||||
# ------------------------------------
|
||||
#
|
||||
# VCore: +1.09 V (min = +0.00 V, max = +1.74 V)
|
||||
# in1: +12.14 V (min = +10.51 V, max = +2.38 V) ALARM
|
||||
#
|
||||
# ^^^ ^^^ ^^^ ^^
|
||||
# $1 $2 $3 $4
|
||||
#
|
||||
#
|
||||
# ------------------------------------
|
||||
|
||||
|
||||
my %config = (
|
||||
fan => {
|
||||
regex => qr/
|
||||
^ # String must start with:
|
||||
([^:\n]*) # Match any non-whitespace char, except ':' and new line
|
||||
# (Match label as \$1)
|
||||
\s* # Zero or more spaces followed by
|
||||
: # : character
|
||||
\s* # Zero or more spaces followed by
|
||||
\+? # Zero or one '+' char. Note: This might not be needed
|
||||
# as FAN speeds don't have + signs in front of them.
|
||||
# This can be probably be removed as the
|
||||
# sensors program never prints a + char in front of
|
||||
# RPM values. Verified in lm-sensors-3-3.1.2
|
||||
(\d+) # Match one or more digits (Match current value as \$2)
|
||||
\s # Exactly one space followed by
|
||||
(?: # a optional group, which might contain the minimum value:
|
||||
RPM.*? # RPM string, and then any chars (but no newlines)
|
||||
(\d+) # Match one or more digits (Match minimum value as \$3)
|
||||
\s # Exactly one space followed by
|
||||
)? # end of optional group
|
||||
RPM # RPM string
|
||||
/xm, # Use extended regular expressions and treat string as multiple lines.
|
||||
title => 'Fans',
|
||||
vlabel => 'RPM',
|
||||
print_threshold => \&fan_threshold,
|
||||
graph_args => '--base 1000 -l 0'
|
||||
},
|
||||
|
||||
temp => {
|
||||
regex => qr/
|
||||
^ # String must start with:
|
||||
([^:\n]*) # Match any non-whitespace char, except ':' and new line
|
||||
# (Match label as \$1)
|
||||
\s* # Zero or more spaces followed by
|
||||
: # ':' character
|
||||
\s* # Zero or more spaces followed by
|
||||
\+? # Zero or one '+' char followed by
|
||||
|
||||
(-? # Match zero or one '-' char
|
||||
\d+ # Match one or more digits
|
||||
# (Match current value as \$2) followed by
|
||||
|
||||
(?:\.\d+)?)# Zero or one match of '.' char followed by one or more
|
||||
# digits. '?:' means it is not a numbered capture group.
|
||||
[°\s] # Match degree char or space char
|
||||
C # Match 'C' char
|
||||
|
||||
(?: # >>>>Match the following statement zero or one time.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\s+ # One or more space followed by
|
||||
\( # '(' char
|
||||
(?:high|limit|crit) # 'high' or 'limit' or 'crit' string.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\s*=\s* # Match zero or more spaces and then '=' char and then
|
||||
# zero or more spaces, followed by
|
||||
\+? # Zero or one '+' char
|
||||
(\d+ # Match one or more digits
|
||||
# (Match high value as \$3) followed by
|
||||
|
||||
(?:\.\d+)?)# Zero or one match of '.' char followed by one or more
|
||||
# digits. '?:' means it is not a numbered capture group.
|
||||
[°\s] # Match degree char or space char
|
||||
C,?\s* # 'C' followed by optional comma and zero or more spaces
|
||||
(?: # >>>Match the following non-capture group zero or more times
|
||||
(?:crit|hyst(?:eresis)?) # 'crit' or 'hyst' string followed by optional 'eresis' string.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\s*=\s* # Match zero or more spaces and then '=' char and then
|
||||
# zero or more spaces, followed by
|
||||
\+? # Zero or one '+' char
|
||||
(\d+ # Match one or more digits
|
||||
# (Match hyst value as \$4) followed by
|
||||
(?:\.\d+)?)# Zero or one match of '.' char followed by one or more
|
||||
# digits. '?:' means it is not a numbered capture group.
|
||||
[°\s]C # Match degree char or space char, and then 'C' char
|
||||
)? # >>>end of group
|
||||
\) # ')' char
|
||||
)? # >>>>end of group
|
||||
/xm, # Use extended regular expressions and treat string as multiple lines.
|
||||
title => 'Temperatures',
|
||||
vlabel => 'degrees Celsius',
|
||||
print_threshold => \&temp_threshold,
|
||||
graph_args => '--base 1000'
|
||||
},
|
||||
|
||||
volt => {
|
||||
regex => qr/
|
||||
^ # String must start with:
|
||||
([^:\n]*) # Match any non-whitespace char, except ':' and new line
|
||||
# one space in front of them.
|
||||
# (match the label as \$1)
|
||||
|
||||
\s*:\s* # Zero or more spaces followed by ':' and
|
||||
# zero or more spaces followed by
|
||||
\+? # Zero or one '+' char followed by
|
||||
(-? # Match zero or one '-' char
|
||||
\d+ # Match one or more digits
|
||||
# (match the current voltage as \$2) followed by
|
||||
(?:\.\d+)?) # Zero or one match of '.' char followed by one or more digits.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\sV # one space, 'V' char
|
||||
|
||||
(?: # >>>>Match the following statement.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\s+ # One or more space followed by
|
||||
\( # '(' char
|
||||
min # Match min string
|
||||
\s*=\s* # Match zero or more spaces and then '=' char and
|
||||
# then zero or more spaces, followed by
|
||||
\+? # Zero or one '+' char
|
||||
(-? # Match zero or one '-' char
|
||||
\d+ # Match one or more digits
|
||||
# (Match the minimum value as \$3) followed by
|
||||
(?:\.\d+)?) # Zero or one match of '.' char followed by one or more
|
||||
# digits. '?:' means it is not a numbered capture group.
|
||||
\sV,\s* # One space char, 'V,' string followed by zero or
|
||||
# more spaces
|
||||
|
||||
max # Match 'max' string
|
||||
\s*=\s* # Match zero or more spaces and then '=' char and
|
||||
# then zero or more spaces, followed by
|
||||
\+? # Zero or one '+' char
|
||||
(-? # Match zero or one '-' char
|
||||
\d+ # Match one or more digits
|
||||
# (Match the max value as \$4) followed by
|
||||
(?:\.\d+)?) # Zero or one match of '.' char followed by one or more digits.
|
||||
# '?:' means passive group (does not match)
|
||||
\sV # one space, 'V' char
|
||||
\) # ')' char
|
||||
)? # >>>>end of statement
|
||||
/xm, # Use extended regular expressions and treat string as multiple lines.
|
||||
|
||||
title => 'Voltages',
|
||||
vlabel => 'Volt',
|
||||
print_threshold => \&volt_threshold,
|
||||
graph_args => '--base 1000 --logarithmic'
|
||||
},
|
||||
|
||||
power => {
|
||||
regex => qr/
|
||||
^ # String must start with:
|
||||
([^:\n]*) # Match any non-whitespace char, except ':' and new line
|
||||
# one space in front of them.
|
||||
# (match the label as \$1)
|
||||
|
||||
\s*:\s* # Zero or more spaces followed by ':' and
|
||||
# zero or more spaces followed by
|
||||
(\d+ # Match one or more digits
|
||||
# (match the power as \$2) followed by
|
||||
(?:\.\d+)?) # Zero or one match of '.' char followed by one or more digits.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\sW # one space, 'W' char
|
||||
|
||||
(?: # >>>>Match the following statement.
|
||||
# '?:' means it is not a numbered capture group.
|
||||
\s+ # One or more space followed by
|
||||
\( # '(' char
|
||||
crit # Match crit string
|
||||
\s*=\s* # Match zero or more spaces and then '=' char and
|
||||
# then zero or more spaces, followed by
|
||||
(\d+ # Match one or more digits
|
||||
# (Match the minimum value as \$3) followed by
|
||||
(?:\.\d+)?) # Zero or one match of '.' char followed by one or more
|
||||
# digits. '?:' means it is not a numbered capture group.
|
||||
\sW\s* # One space char, 'W' character followed by zero or
|
||||
# more spaces
|
||||
\) # ')' char
|
||||
)? # >>>>end of statement
|
||||
/xm, # Use extended regular expressions and treat string as multiple lines.
|
||||
|
||||
title => 'Power',
|
||||
vlabel => 'Watts',
|
||||
print_threshold => \&power_threshold,
|
||||
graph_args => '--base 1000 --logarithmic'
|
||||
},
|
||||
);
|
||||
|
||||
if ( defined $ARGV[0] and $ARGV[0] eq 'autoconf' ) {
|
||||
# Now see if "sensors" can run
|
||||
my $text = `$SENSORS 2>/dev/null`;
|
||||
if ($?) {
|
||||
if ($? == -1) {
|
||||
print "no (program $SENSORS not found)\n";
|
||||
} else {
|
||||
print "no (program $SENSORS died)\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
unless ($text =~ /[° ]C/) {
|
||||
print "no (no temperature readings)\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
print "yes\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if (defined $ARGV[0] and $ARGV[0] eq 'suggest') {
|
||||
my $text = `$SENSORS 2>/dev/null`;
|
||||
foreach my $func (keys %config) {
|
||||
print $func, "\n" if $text =~ $config{$func}->{regex};
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
$0 =~ /sensors_(.+)*$/;
|
||||
my $func = $1;
|
||||
exit 2 unless defined $func;
|
||||
|
||||
if ( defined $ARGV[0] and $ARGV[0] eq 'config' ) {
|
||||
print "graph_title $config{$func}->{title}\n";
|
||||
print "graph_vlabel $config{$func}->{vlabel}\n";
|
||||
print "graph_args $config{$func}->{graph_args}\n";
|
||||
print "graph_category sensors\n";
|
||||
my $text = `$SENSORS`;
|
||||
my $sensor = 1;
|
||||
while ($text =~ /$config{$func}->{regex}/g) {
|
||||
my ($label, undef, $max, $min) = ($1, $2, $3, $4);
|
||||
print "$func$sensor.label $label\n";
|
||||
$config{$func}->{print_threshold}->($func.$sensor, $3, $4);
|
||||
print "$func$sensor.graph no\n" if exists $ENV{"ignore_$func$sensor"};
|
||||
$sensor++;
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $text = `$SENSORS`;
|
||||
my $sensor = 1;
|
||||
while ($text =~ /$config{$func}->{regex}/g) {
|
||||
print "$func$sensor.value $2\n";
|
||||
$sensor++;
|
||||
}
|
||||
|
||||
sub fan_threshold {
|
||||
my $name = shift;
|
||||
my $min = shift;
|
||||
|
||||
my $warn_percent = exists $ENV{fan_warn_percent} ? $ENV{fan_warn_percent} : 5;
|
||||
|
||||
return unless defined $min;
|
||||
|
||||
printf "$name.warning %d:\n", $min * (100 + $warn_percent) / 100;
|
||||
printf "$name.critical %d:\n", $min;
|
||||
}
|
||||
|
||||
sub temp_threshold {
|
||||
my $name = shift;
|
||||
my $max = shift;
|
||||
my $min = shift;
|
||||
|
||||
if (defined($min) and defined($max) and $min > $max) {
|
||||
($min, $max) = ($max, $min);
|
||||
}
|
||||
|
||||
printf "$name.warning $min\n" if $min;
|
||||
printf "$name.critical $max\n" if $max;
|
||||
}
|
||||
|
||||
sub volt_threshold {
|
||||
my $name = shift;
|
||||
my $min = shift;
|
||||
my $max = shift;
|
||||
my $warn_percent = exists $ENV{volt_warn_percent} ? $ENV{volt_warn_percent} : 20;
|
||||
|
||||
return unless defined ($min && $max);
|
||||
|
||||
my $diff = $max - $min;
|
||||
my $dist = $diff * $warn_percent / 100;
|
||||
printf "$name.warning %.2f:%.2f\n", $min + $dist, $max - $dist;
|
||||
printf "$name.critical $min:$max\n";
|
||||
}
|
||||
|
||||
sub power_threshold {
|
||||
my $name = shift;
|
||||
my $crit = shift;
|
||||
my $warn_percent = exists $ENV{watt_warn_percent} ? $ENV{watt_warn_percent} : 20;
|
||||
|
||||
return unless defined ($crit);
|
||||
|
||||
printf "$name.warning :%.2f\n", $crit * (100-$warn_percent)/100;
|
||||
printf "$name.critical :$crit\n";
|
||||
}
|
||||
|
||||
# vim:syntax=perl
|
||||
Reference in New Issue
Block a user