mirror of
https://github.com/munin-monitoring/contrib.git
synced 2018-11-08 00:59:34 +01:00
201 lines
6.5 KiB
Perl
Executable file
201 lines
6.5 KiB
Perl
Executable file
#!/usr/bin/perl -w
|
|
|
|
=cut
|
|
|
|
=head1 NAME
|
|
|
|
ping - Plugin to monitor ping times
|
|
|
|
=head1 CONFIGURATION
|
|
|
|
ping_args - Arguments to ping (default "-c 2 -w 1")
|
|
ping_args2 - Arguments after the host name (required for Solaris)
|
|
ping - Ping program to use
|
|
ping6 - Ping program to use with IPv6
|
|
hosts - List of comma-separated hosts to ping (IPv4/6 address or FQDN)
|
|
You can prepend host name with:
|
|
'A:' - to resolve all IPv4 addresses
|
|
and create an entry per address (requires 'host' program)
|
|
'AAAA:' - the same for IPv6 (requires 'host' program)
|
|
'6:' - do not try to resolve, but use ping6 for this host
|
|
names - Friendly display name of each host given in the "hosts" parameter (comma-separated list).
|
|
If not set, "hosts" elements will be used
|
|
fork - If set to non-zero, fork each ping into parallel process to ping asynchronously
|
|
|
|
Configuration example
|
|
|
|
[ping*]
|
|
env.hosts mail.example.org,6:www.example.org,AAAA:search.example.org
|
|
env.names Mail,Web,Search
|
|
env.fork yes
|
|
|
|
Configuration example for Solaris
|
|
|
|
[ping*]
|
|
env.host www.example.org mail.example.org
|
|
env.ping_args -s
|
|
env.ping_args2 56 2
|
|
|
|
You can also append '_packetloss' to the plugin filename for packet loss statistics.
|
|
|
|
=head1 AUTHOR
|
|
|
|
Original Perl script Copyright (C) 2008 Thomas Gutzler (thomas.gutzler@gmail.com)
|
|
Original Shell script Copyright (C) 2004 Jimmy Olsen
|
|
|
|
=head1 LICENSE
|
|
|
|
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; version 2 dated June,
|
|
1991.
|
|
|
|
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, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
=head1 MAGIC MARKERS
|
|
|
|
#%# family=manual
|
|
|
|
=cut
|
|
|
|
use strict;
|
|
use Munin::Plugin;
|
|
|
|
my $ping = exists $ENV{ping} ? $ENV{ping} : "ping";
|
|
my $ping6 = exists $ENV{ping6} ? $ENV{ping6} : "ping6";
|
|
# Since ping sends a packet every second (-i 1) by default,
|
|
# we may need 2 total seconds (-w 2) for <1000msec replies
|
|
my $ping_args = exists $ENV{ping_args} ? $ENV{ping_args} : "-c 2 -w 2";
|
|
my $ping_args2 = exists $ENV{ping_args2} ? $ENV{ping_args2} : "";
|
|
my $fork = exists $ENV{fork} ? $ENV{fork} : 0;
|
|
my $packetloss_mode = ($0 =~ /_packetloss$/);
|
|
|
|
my @host_options = exists $ENV{hosts} ? split(/,/, $ENV{hosts}) : "A:www.google.com";
|
|
|
|
# bare addresses
|
|
my @host_addrs = @host_options;
|
|
|
|
# ping program to use
|
|
my @host_ping = ($ping) x @host_options;
|
|
|
|
# resolve record type, if specified
|
|
my @host_resolv = (0) x @host_options;
|
|
|
|
my $config_mode = ($ARGV[0] and $ARGV[0] eq 'config');
|
|
if ($config_mode) {
|
|
print "graph_title " . ($packetloss_mode ? "Ping packet loss" : "Ping times") . "\n";
|
|
print "graph_args --base 1000 -l 0\n";
|
|
print "graph_vlabel " . ($packetloss_mode ? "%" : "seconds") . "\n";
|
|
print "graph_category network\n";
|
|
print "graph_info This graph shows ping " . ($packetloss_mode ? "packet loss" : "RTT") . " statistics.\n";
|
|
}
|
|
|
|
for (my $host_option = 0; $host_option < @host_options; ++$host_option) {
|
|
my $h_addr = $host_options[$host_option];
|
|
my @config = split(/:/, $h_addr, 2);
|
|
if ($#config) {
|
|
my $h_ping = $ping;
|
|
my $h_resolv = 0;
|
|
if ($config[0] eq "6") {
|
|
# user wants this host to be pinged via IPv6
|
|
$h_ping = $ping6;
|
|
$h_addr = $config[1];
|
|
} elsif ($config[0] eq "A") {
|
|
# user wants this host to be resolved via IPv4
|
|
$h_resolv = "A";
|
|
$h_addr = $config[1];
|
|
} elsif ($config[0] eq "AAAA") {
|
|
# user wants this host to be resolved as IPv6
|
|
$h_resolv = "AAAA";
|
|
$h_addr = $config[1];
|
|
$h_ping = $ping6;
|
|
} elsif ($config[0] =~ /^[[:xdigit:]]+$/) {
|
|
# this is IPv6 addr
|
|
$h_ping = $ping6;
|
|
} else {
|
|
# let 'host' decide what resolve type do we need
|
|
$h_resolv = $config[0];
|
|
$h_addr = $config[1];
|
|
}
|
|
$host_addrs[$host_option] = $h_addr;
|
|
$host_resolv[$host_option] = $h_resolv;
|
|
$host_ping[$host_option] = $h_ping;
|
|
}
|
|
}
|
|
|
|
# display names
|
|
my @host_names = exists $ENV{names} ? split(/,/, $ENV{names}) : @host_addrs;
|
|
|
|
if (@host_names != @host_addrs) {
|
|
print "Warning: host names specified does not match addresses\n";
|
|
}
|
|
|
|
# forked children
|
|
my @children = ();
|
|
|
|
for (my $host_i = 0; $host_i < @host_addrs; ++$host_i) {
|
|
my @h_addrs = ($host_addrs[$host_i]);
|
|
my $h_ping = $host_ping[$host_i];
|
|
my $h_resolv = $host_resolv[$host_i];
|
|
my $h_name = ($host_names[$host_i] or $h_addrs[0]);
|
|
|
|
if ($h_resolv) {
|
|
# we have to resolve the host to (probably multiple) addresses
|
|
my $h_base_addr = pop @h_addrs;
|
|
my @host = `host -t $h_resolv $h_base_addr`;
|
|
chomp @host;
|
|
for (my $h_host_i = 0; $h_host_i < @host; ++$h_host_i) {
|
|
my $h_host = $host[$h_host_i];
|
|
my ($h_addr) = $h_host =~ /address (.*)$/;
|
|
if ($h_addr) {
|
|
push @h_addrs, $h_addr;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (my $h_addr_i = 0; $h_addr_i < @h_addrs; ++$h_addr_i) {
|
|
my $h_addr = $h_addrs[$h_addr_i];
|
|
my $h_cur_name = $h_resolv ? $h_name . " ($h_addr)" : $h_name;
|
|
my $h_norm_name = clean_fieldname($h_cur_name);
|
|
if ($config_mode) {
|
|
print "$h_norm_name.min 0\n$h_norm_name.label $h_cur_name\n$h_norm_name.draw LINE2\n";
|
|
my ( $warning, $critical ) =
|
|
get_thresholds($h_norm_name);
|
|
printf "%s.warning %s\n", $h_norm_name, $warning
|
|
if $warning;
|
|
printf "%s.critical %s\n", $h_norm_name, $critical
|
|
if $critical;
|
|
} else {
|
|
my $pid = $fork ? fork() : -1;
|
|
if ($pid <= 0) {
|
|
# either we can't fork, or don't want to, or we are child
|
|
my @ping = `$h_ping $ping_args $h_addr $ping_args2`;
|
|
chomp @ping;
|
|
my $ping = join(" ", @ping);
|
|
my $ping_time = "U";
|
|
my $packet_loss = "U";
|
|
$ping_time = ($1 / 1000) if ($ping =~ m@min/avg/max.*\s\d+(?:\.\d+)?/(\d+(?:\.\d+)?)/\d+(?:\.\d+)?@);
|
|
$packet_loss = $1 if ($ping =~ /(\d+)% packet loss/);
|
|
print "$h_norm_name.value ". ($packetloss_mode ? $packet_loss : $ping_time) . "\n";
|
|
if ($pid == 0) {
|
|
# this is a child process, don't forget to exit
|
|
exit(0);
|
|
}
|
|
} else {
|
|
# in parent
|
|
push @children, $pid;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (my $child_i = 0; $child_i < @children; ++$child_i) {
|
|
waitpid($children[$child_i], 0);
|
|
}
|