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