http://www.perlmonks.org?node_id=88074

derek3000 has asked for the wisdom of the Perl Monks concerning the following question:

Hi. I'm writing a little batch pinging utility that asks for the third octet and then scans the fourth from 1-255. I want the ping results to go to a log file, and then to scan that log file for a line containing "x bytes from 10.32.z.y" so that i know that ip is taken. The code is below. First though, I want to make sure my problems are clear: 1. It prints nothing to "ips.txt", even though ping fills out "log.txt" fine. 2. Styllistically, I want any suggestions to make the code more idiomatic.
---------------------------------------------------------------------- +----- #!/usr/bin/perl -w use strict; print "Please enter the third octet for scannin': "; my $octet3 = <>; chomp $octet3; open(LOG, ">log.txt") || die "Couldn't open log file: $! \n"; for(my $x = 0; $x < 20; $x++){ open(PINGIN, "ping 10.32.$octet3.$x -w 5 |") or die "Couldn't pull that one off: $! \n"; while(<PINGIN>){ warn "Logging activity for 10.32.$octet3.$x \n"; print LOG $_; } } close PINGIN; close LOG; open(LOG, "log.txt") or die "$!"; open(UNAVAILABLE, ">ips.txt") or die "$!"; while(my $line = <LOG>){ if($line =~ /^64 bytes from ([0-9.]):/){ my $ip = $1; print UNAVAILABLE "$ip is unavailable.\n"; } } close LOG; close AVAILABLE; --------------------------------------------------------------------
any help would be much appreciated. Thanks, Derek

Replies are listed 'Best First'.
Re: batch ping problem
by marcink (Monk) on Jun 13, 2001 at 19:18 UTC
    How about using Net::Ping to do the checking?

    As for the 'styllistic' part:
    1. small tools like this should not be interactive -- if they get all the needed data from command line (@ARGV) they are easier to reuse in bigger scripts.
    2. The /^64 bytes from ([0-9.]):/ will never match -- should be /^64 bytes from ([0-9.])*:/. Even then, finding such a line will mean that host $1 is available.
    3. You're making the task more complex than it really is -- why dump all that data in one log file and then try to make sense of it if you could analyze it immediately after running ping?
    4. Easier way of getting ping's output: my $t = `ping...`;

    Update: See the example on `man Net::Ping` -- it does exactly what you need, you just have to fill in the address array. -mk
Re: batch ping problem
by Henri Icarus (Beadle) on Jun 13, 2001 at 19:27 UTC
    Derek,

    There are a number of errors in your code. For one, you are opening PINGIN inside the loop but only closing it outside the loop. Also your regular expression search when looking throught the log is missing a * so it will never match (it should be "([0-9.]*)" )

    Finally I think you've got the case wrong, because ping returns the 64 bytes line when machines are available!

    All that aside, there's a much easier way to do what you're trying to do, just use the backtick operator, like this:

    $ip = "10.32.$octet3.$x"; @data = `ping $ip -w 5`;
    That will load the results of the command into an array which you can then process with a single grep command:
    print "$ip is not available" if !grep(/^64 bytes from/,@data);

    Enjoy!

    -I went outside... and then I came back in!!!!

Re: batch ping problem
by derek3000 (Beadle) on Jun 13, 2001 at 19:40 UTC
    thanks for the help monks. I think i should have made my idea here a little clearer: I want to find ip's that don't return anything, so I know that they are free to put a new machine on. anyway, I knew there was some easier way to do it. I'm still a newbie, which is why I asked what I could do to make it more simple--newbies usually do things the hardest way possible. Thanks again.
Re: batch ping problem
by Anonymous Monk on Jun 13, 2001 at 22:54 UTC
    Try to set the last octet to 255 like @x=`ping 10.32.$x.255 -w`. It should make the work easier.