perlquestion
dguntner
Well, I'm down to the nitty-gritty at last! :-) The script to produce a list of hosts pinged is working, but I haven't got a clue as to how to sort the list by ping time. Here's the script in its current form:<p>
<code>
#!/usr/bin/perl -w
#
# Ping a range of IP addresses, and list sorted by ping time.
#
# This uses the ICMP echo method instead of UDP echo, as
# some routers don't pass UDP echo. Also, if the remote host
# doesn't have an appropriate service listening on the UDP
# echo port, it won't answer.
#
# D. Guntner, 21-July-2007
# Ver 1.0, 21-July-2007
use Net::Ping;
use Net::Netmask;
die "I need root privs to run, dude.\n" unless $> == 0;
# Get the IP address(es)
my $netaddr = shift(@ARGV);
usage() unless $netaddr; # Give usage message if no input
my $hostname = "";
my $block = new Net::Netmask($netaddr);
my @hosts = $block->enumerate();
my $p = Net::Ping->new("icmp");
$p->hires(); # Comment out this line if no Time::HiRes installed
# (Or better yet, install Time::HiRes... :-) )
# Create our host list to sort from
open OF, ">hostlist.txt" or die "Can't create hostlist.txt: $!";
select OF;
$|++; # Unbuffer output file
select STDOUT;
print("Now scanning $netaddr, please wait....\n");
foreach $host (@hosts) {
($ret, $duration, $ip) = $p->ping($host, 5.5);
if ($ret) {
printf OF ("%s [ip: $ip] is alive %.2f ms)\n", gethostbyip($host), 1000 * $duration);
}
}
close OF;
$p->close();
print("Now sorting the list....\n");
open IF, "<hostlist.txt" or die "Can't open hostlist.txt for input: $!";
my @data = <IF>;
close IF;
# Don't need the file anymore, so delete it
#if (unlink("hostlist.txt") > 0) {
# print("Couldn't remove hostlist.txt file for some reason....\n");
#}
my @sorted = map {s/(^|\D)0+(\d)(?=\t)/$1$2/g; $_}
sort
map {s/(\d+)(?=\t)/sprintf"%03.3d",$1/ge; $_}
@data;
print(@sorted);
sub gethostbyip {
use Socket;
my $hostip = $_[0];
my $iaddr = inet_aton($hostip);
my $hostname = gethostbyaddr($iaddr, AF_INET);
$hostname = $hostip unless defined $hostname;
return $hostname;
}
sub usage {
use File::Basename;
my $progname = basename($0);
print <<"EO_USAGE";
This script will ping scan a range if IP addresses, and return
a list sorted by ping time. Give address in CIDR format.
Usage: $progname {IP/NETMASK}
Example: $progname 1.2.3.4/24
You *could* put in only a single IP address, but there wouldn't
be much point to that, now would there? :-)
EO_USAGE
exit;
}
</code>
The "my @sorted" section there I copied as a placeholder from another script that was in one of the messages here, so I'd know the basic formula/idea. However, I don't know what that stuff should be changed to in order to get the sorting order I want. (Oh yea, and the "if" that's checking on the unlink to get rid of the file isn't working, either - the file unlinks fine but I always get the message. *grin*)<p>
The script provides output in the format of:<p>
<code>
some.host.name [ip: 111.222.333.444] is alive 70.05 ms)
</code>
What I need is to sort that output by that last value there - the latency time. I don't suppose there's a sort wizard here, who can tell me what the sort in my script needs to be changed to, so that it works as needed? :-)<p>
--Dave