When you construct the @iparray, you put a newline after each IP. Then when you use the @iparray to print out $host is alive, the newline is in the middle of whatever line it is you're printing.
Additionally, you have no newline at the end of the print " $host is alive "; line, thus garbling your output a bit.
Take the \n out of your map, and put one in your print to get one correctly formatted result on each line. | [reply] [d/l] [select] |
I'm not sure I'm understanding your problem entirely, but try it this way:
$ipnumber ="128.135.75.";
@iparray = map $ipnumber.$_,1..254 ;
# no chomps needed
...
foreach my $host (@iparray) {
if ( $p->ping($host)){
print "$host is alive\n";
}
}
...
MeowChow
s aamecha.s a..a\u$&owag.print | [reply] [d/l] |
Interesting problem. I had a similar one myself, except I don't really care which ones are up, just which ones are down, and I needed the results as a percentage so I could graph them.
I also discovered that trying to ping a huge number of hosts one at a time was painfully slow, so I wrote the following.
Bear in mind that this program is designed to pull the list of targets from a MySQL database, you could easily modify it to read in a config file though. It also doesn't handle forking the most efficient way possible, in that it doesn't ALWAYS keep $maxforks children running, it just runs them in bursts of $maxforks, but I find it's plenty fast enough even when pinging several hundred targets. I also used the system call to ping instead since I couldn't install CPAN modules on the machine it was running on. Again, that's probably a three-minute change.
Hope you find it interesting...
#!/usr/bin/perl --
#
# ForkingPinger
# Pings a list of remote hosts and calculates an uptime
# percentage based on the number of responses. If run in
# interactive mode, lists the sites that failed.
#
# (C) 2001 James Mancini <wfe@networkavatar.com>
# Please send copies of modifications or improvements to
# the author!
#
# Released under the same terms as perl itself.
#
# THIS PROGRAM IS PROVIDED WITH NO WARRANTY - USE AT YOUR
# OWN RISK.
#
# 21 Mar 2001
my $Version = "0.2.2 - beta";
use DBI;
use Getopt::Long;
use POSIX ":sys_wait_h";
$|++; #autoflush output for speed
#########################
# MAIN
#########################
my (%opt, @targets);
my $maxprocs = $opt{max} || 50; # set the maximum number of childre
+n to spawn
$main::avail = 0;
&options(\%opt);
&get_targets();
&check_remotes();
#########################
sub get_targets
#########################
{
## Set up vars for main db call
my ($dsn) = "DBI:mysql:routers:localhost";
my ($user_name) = "user";
my ($password) = "abcd1234";
my ($dbh, $sth);
## Connect to DB
$dbh = DBI->connect ( $dsn, $user_name, $password, {RaiseError =>1} );
## Fetch variables from database and write out config file
## The Database Query is option dependant
if ($opt{cat})
{
$sth = $dbh->prepare ("SELECT ip FROM routers WHERE category rlike
+ '$opt{cat}'");
} elsif ($opt{all}) {
$sth = $dbh->prepare ("SELECT ip FROM routers");
} else { die "ERROR - Couldn't identify a target. $!"; }
## Go get it
$sth->execute();
## Process the data
while( ($ip_add) = $sth->fetchrow_array() )
{
push @targets, $ip_add;
$noerror = "1";
}
## Disconnect the DB
$sth->finish ();
$dbh->disconnect();
unless ($noerror) {die "FATAL: Database did not return valid data! Che
+ck Device name.\nError Response: $!\n";}
}
#########################
sub check_remotes
#########################
{
my $prox = int(scalar(@targets)/$maxprocs);
my $prox_r = int(scalar(@targets)%$maxprocs);
my $i = 0;
if ($prox)
{
for ( 1 .. $prox ) # call the forking routine as many times as requ
+ired to get most of the targets
{
&breed($maxprocs);
}
}
if ($prox_r)
{
&breed($prox_r); # Then call the forking routine but this time on
+ly enough to catch the modulo
}
# Calculate results and print to STDOUT
my $uptime = ( $main::avail / scalar(@targets) ) * 100; # return res
+ults as a percentage
$uptime = sprintf('%.2f',$uptime);
print "\nTOTAL:\t${uptime}% of devices are responding.\n";
}
#########################
sub breed ($)
#########################
{
my $loop = shift;
for ( 1 .. $loop )
{
if ($pid=fork) {
push @pids, $pid;
$i ++;
} elsif (defined $pid) {
my $next = @targets[${i}];
&ping_remote($next);
exit;
}
}
foreach my $childpid (@pids)
{
waitpid($childpid, 0);
$main::avail += ! $?; # 0 means success, non-zero means failure
}
}
#########################
sub ping_remote($)
#########################
{
my $ip = shift;
my $response = `ping -n -w 5 -i .3 $ip -c 3 | grep round-trip`;
chomp $response;
if ($response) { $response = 0; } else { $response = 1; } # 0 means su
+ccess, non-zero means failure
if (-t and $response) { print "Failed connect to $ip\n"; }
exit($response);
}
########################
sub options ()
########################
{
my $opt = shift;
GetOptions( $opt,
'cat=s',
'max=s',
'all',
);
$opt{cat} =~ s/[\"\;]//; # remove quotes and semicolons from querie
+s
unless (defined $opt{cat} || $opt{all}) #print usage if options not
+ given
{
print <<ECHO;
ForkingPinger, Version $Version
---------
Pulls a category from the database and checks it for availability, ret
+urning a percentage.
Designed to be run in batch mode but can be used at the command line f
+or debugging or testing purposes. Highly parallel.
Automatically prints the IP addresses of failed sites if used from the
+ command line.
Usage: $0 [options]
Options:
--cat=name
Pull all devices of category matching regexp 'name' from DB and test a
+vailability.
--all
Pull all devices from DB and test availability.
--max=num
Spawn no more than num processes in parallel (default = 50)
ECHO
exit(1);
}
}
Update: Fixed a little typo I spotted. Oops.
Update2: Fixed a bigger omission: the -all switch was broken. I wasn't considering the option when validating command line switches. Oops again.
Signature void where prohibited by law. | [reply] [d/l] |
I can't resist mentioning that at first glance, I read your title as Porking Finger, a spoonerism which would certainly qualify as a Cool Use For PerlTM.
MeowChow
"you can prick your finger, but don't finger your prick" - George Carlin | [reply] |
Don't know exactly what your problem is, but if you change the print-line to:
print " $host is alive \n";
it will print:
10.1.1.1 is alive
10.1.1.2 is alive
10.1.1.3 is alive
| [reply] [d/l] [select] |
After the map() statement you do a useless chomp of $ipnumber. did you mean to do that to @iparray instead? That could mess up the ping module, I suppose.
When's the last time you used duct tape on a duct? --Larry Wall | [reply] [d/l] |
I assume that it's supposed to be
128.135.75.1 is alive ???
Try removing the newline in this part @iparray = map $ipnumber. ".$_\n",1..254 ; And adding a newline to foreach my $host (@iparray) {
if ( $p->ping( $host )){
print " $host is alive\n ";
at the end of that. Otherwise when it goes to print the host it copies the newline from the original array. And hence the return at the end of the IP Address. So the final product should look like this (Note: I change the ips to match my network)
#!/usr/bin/perl
use warnings;
use Net::Ping;
use Socket;
$ipnumber ="192.168.30";
chomp $ipnumber;
@iparray = map $ipnumber. ".$_",1..254 ;
chomp $ipnumber;
#open (ERRORLOG, ">errorlog");
#open (OFFLINE,">offline");
#open (ONLINE,">online");
my $proto = 'icmp';
my $def_timeout = '5';
my $bytes = '64';
my $p = Net::Ping->new($proto, $def_timeout , $bytes);
foreach my $host (@iparray) {
if ( $p->ping( $host )){
print " $host is alive\n ";
}
#foreach my $host (@iparray) {
# $testing = $p $host;
# print "$testing";
# print "$host offline " unless $p->ping($host,1);
# print "$host online " unless $p->ping($host,0);
# print ERRORLOG "$host offline " unless $p->ping($host,1);
# print OFFLINE "$host"unless $p->ping($host,1);
# print ONLINE "$host online" unless $p->ping($host,0);
}
$p->close();
Sgt
| [reply] [d/l] [select] |
Damn! This code is posted twice in the Monastery and I
just happened to comment on the dead thread. Anyway I just
wanted to point out that I have code that does much the
same thing, with a few more bells and whistles. You may
find it of use.
-- g r i n d e r
| [reply] |