1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use Data::Dumper;
use Time::HiRes qw(time);
use Statistics::Descriptive;
=head1 NAME
ping-monitor.pl - Live ping statistics
=head1 SYNOPSIS
ping-monitor.pl <host>
=head1 DESCRIPTION
ping-monitor.pl provides live mean, median, standard deviation and packet loss
statistics similar to ping(8). The statistics are calculated over the last 10
seconds by default.
=cut
if (0+@ARGV < 1) {
print "usage: $0 <host>\n";
exit 0;
}
my $host = $ARGV[0];
# a value < 0.2 requires root privileges
my $frequency = 0.2;
# 10 second average
my $window_size = 10/$frequency;
open my $ping, "-|", "ping -nDOi $frequency -W 1 $host";
my @history;
my $last_reply = 0;
# ensure we are on a clean line for cleaning later
printf "\n";
while (<$ping>) {
next if m/^PING /;
if (m/^\[(?<ts>[0-9.]+)\] \d+ bytes from [^:]+: icmp_seq=\d+ ttl=\d+ time=(?<time>[0-9.]+) ms$/) {
push @history, {
timestamp => $+{ts},
time => $+{time},
};
$last_reply = $+{ts} if $+{ts} > $last_reply;
} elsif (m/^\[(?<ts>[0-9.]+)\] no answer yet for icmp_seq=\d+$/) {
push @history, {
timestamp => $+{ts},
time => undef,
};
}
if (0+@history > $window_size) {
splice @history, 0, 1;
}
my $avg_lost = 0.0;
my $stats = Statistics::Descriptive::Full->new();
for my $x (@history) {
$stats->add_data($x->{time}) if defined $x->{time};
$avg_lost += 1 if not defined $x->{time};
}
$avg_lost /= @history if @history > 0;
my $last_reply_diff = 0;
$last_reply_diff = time - $last_reply if $last_reply;
# clear 1 line
printf "[%dF[0J", 0;
my @parts;
if ($stats->mean()) {
push @parts, sprintf "avg/median/stdev/max time: %0.2fms/%0.2fms/%0.2fms/%0.2fms", $stats->mean(), $stats->median(), $stats->standard_deviation(), $stats->max();
}
push @parts, sprintf "avg loss: %0.2f%%", $avg_lost*100 // 0.0;
if ($last_reply_diff > 0.5) {
push @parts, sprintf "last reply: %0.3fs ago", $last_reply_diff;
}
print join(", ", @parts)."\n";
#print Dumper(\@history);
#print Dumper($avg_time, $avg_lost, $last_reply);
}
|