Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Multi-threading ping of a list of hosts.....Again!

by blackadder (Hermit)
on Sep 20, 2004 at 11:15 UTC ( [id://392326]=perlquestion: print w/replies, xml ) Need Help??

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

Dear All,

I have a list containing thousands upon thousands of Win32Xp based hostnames that I need to ping the lot of them! Simultaneously! And, I have this bit of code to do that (....!)
$|++; require 5.008; use strict; use vars qw /@childs $child @list/; use threads; use threads::shared; my @up: shared; my @down: shared; sub ping_hosts { my ($ip) = @_; print "Testing : $ip\n"; my $resp = `ping $ip`; print "$resp\n"; if ($_=~ /reply/i) { push @up, "$ip : Up\n"; } else { push @down, "$ip : Down\n"; } } open (LST, "c:\\list.txt")||die "$^E : $!\n"; chomp (@list=<LST>); foreach(@list) { push @childs, threads->create("ping_hosts","$_"); } foreach $child (@childs) { eval {$child->join();}; } print @up; print "\n________________________\n"; print @down;
However, the script doesn’t seem to work at all! It basically just hangs without any errors!

Have I missed out something of dire importance that made this script hang? It just seems that everything about the script is correct! Yet no output…..Can the blessed/holy ones enlighten me with answers as to the reason why please.

Thanks indeed.

Btw : Is Multithreading in Perl5.8.4 stable? recommended?
Blackadder

Replies are listed 'Best First'.
Re: Multi-threading ping of a list of hosts.....Again!
by borisz (Canon) on Sep 20, 2004 at 11:41 UTC
    Better use Net::Ping it can ping to all your hosts at once and wait for some defined time then it reports back who responds.
    And the best, it works without (i)threads at all.
    Boris
      ... it can ping to all your hosts at once ...

      It can? How?


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
        This example scan 253 hosts on my home wlan in 5 seconds. Change the TIMEOUT and or the ips array as you like.
        use Net::Ping; # fill this array with your ips my @ips = map { "192.168.1." . $_ } ( 2 .. 254 ); my @ips_up; use constant { TIMEOUT => 5000, PORT => 7 }; my $p = Net::Ping->new( "syn", TIMEOUT() / 1000 ); $p->{port_num} = PORT; $p->ping($_) for (@ips); while ( my ( $host, $rtt, $ip ) = $p->ack ) { push @ips_up, $ip; } local $" = "\n"; print @ips_up;
        Boris
Re: Multi-threading ping of a list of hosts.....Again!
by gaal (Parson) on Sep 20, 2004 at 11:22 UTC
    If my memory serves, nmap has some excellent parallel ping code.
      Lots of cool tools in there,.....its BookMarked now.

      Found something like 'Ping Sweep' and other,.....

      Thanks for that.
Re: Multi-threading ping of a list of hosts.....Again!
by NetWallah (Canon) on Sep 20, 2004 at 17:28 UTC
    Here is some working multi-threaded ping code I wrote a while back. Works on Win32.
    #!/usr/bin/perl -w # Parallel Pinger... use strict; use threads; use Thread::Queue; use Net::Ping; my $master = $$; my $verbose = $ARGV[0] eq q(-v); my $RequestQ = Thread::Queue->new; my $ResultQ = Thread::Queue->new; my $threadcount = 20; my @kids; # Generate list of hosts to ping my @targets; foreach my $target (1..95) { $RequestQ->enqueue ('10.2.56.' . $target); } for (0..($threadcount - 1)){ $RequestQ->enqueue(undef); push @kids, threads->new(\&Ping_it, $_); } foreach (threads->list){ $_->join; } $ResultQ->enqueue(undef); # Last item while (my $target = $ResultQ->dequeue){ print " $target\n"; } ############################################# sub Ping_it{ my ($work_count, $miss_count); my $t = shift; my $pinger = Net::Ping->new('icmp', 1); while (my $target = $RequestQ->dequeue){ $work_count ++; my $retval = 0; $verbose and print "Child $target started\n"; if($pinger->ping($target)) { # PING! Throw it in the FIFO $verbose and print "Found $target!\n"; $retval=1 } else { warn "Thread $t $target: $!\n"; $verbose and print "No response from $target\n"; $retval=0; $miss_count++; } $ResultQ->enqueue ($target . "=" . $retval); threads->yield(); $verbose and print "Child $target exiting\n"; } $pinger->close(); $ResultQ->enqueue("Thread $t processed $work_count, missed $miss_co +unt"); }

        Earth first! (We'll rob the other planets later)

      A couple of questions about your code:

      1. Why accumulate your thread handles into @kids when you never use them again?
      2. Why not detach the threads at creation when you don't use the returns?

      Please note. There is no implied critism here, just comparing notes.

      FWIW, I like your technique of enqueuing undefs to terminate your loops. It's much cleaner than several things I've used.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
        I sort of "converted" someone elses program model, and never cleaned it up after proving that it worked , so it has leftover junk. Since this was just a "test program", I did not bother to do the cleanup, so, points taken. Thanks.

            Earth first! (We'll rob the other planets later)

      All my hosts are Netbios names. Do I have convert them to an IP address instead to use it in this script?

      Thanks
      Not Sure if it worked or not!

      I modified the script to;
      use strict; use Win32; use Win32::AdminMisc; use threads; use Thread::Queue; use Net::Ping; my $master = $$; my $verbose = $ARGV[0] eq q(-v); my $RequestQ = Thread::Queue->new; my $ResultQ = Thread::Queue->new; my $threadcount = 20; my @kids; my @targets; while (<DATA>) { chomp; print "$_ : "; my $ip_address = Win32::AdminMisc::gethostbyname($_); print "$ip_address\n"; push (@targets, $ip_address); } # Generate list of hosts to ping foreach my $target (@targets) { $RequestQ->enqueue ($target); } for (0..($threadcount - 1)){ $RequestQ->enqueue(undef); push @kids, threads->new(\&Ping_it, $_); } foreach (threads->list){ $_->join; } $ResultQ->enqueue(undef); # Last item while (my $target = $ResultQ->dequeue){ print " $target\n"; } ############################################# sub Ping_it{ my ($work_count, $miss_count); my $t = shift; my $pinger = Net::Ping->new('icmp', 1); while (my $target = $RequestQ->dequeue){ $work_count ++; my $retval = 0; $verbose and print "Child $target started\n"; if($pinger->ping($target)) { # PING! Throw it in the FIFO $verbose and print "Found $target!\n"; $retval=1 } else { warn "Thread $t $target: $!\n"; $verbose and print "No response from $target\n"; $retval=0; $miss_count++; } $ResultQ->enqueue ($target . "=" . $retval); threads->yield(); $verbose and print "Child $target exiting\n"; } $pinger->close(); $ResultQ->enqueue("Thread $t processed $work_count, missed $miss_co +unt"); } __DATA__ SN02GEY10a SN02GEZ10a SN02GFC09a SN02GEY09a SN02GEZ09a SN02GEY05a SN02GEY06a SN02GEY07a SN02GEY08a SN02GEZ05a SN02GEZ06a
      And the output was;
      C:\Perl>ping_sweep2.pl SN02GEY10a : 172.24.175.53 SN02GEZ10a : 172.24.166.15 SN02GFC09a : 172.24.184.43 SN02GEY09a : 172.24.184.21 SN02GEZ09a : 172.24.175.10 SN02GEY05a : 172.24.166.48 SN02GEY06a : 172.24.175.43 SN02GEY07a : 172.24.184.12 SN02GEY08a : 172.24.166.13 SN02GEZ05a : 172.24.175.55 SN02GEZ06a : 172.24.184.46 172.24.175.53=1 172.24.166.15=1 172.24.184.43=1 172.24.175.10=1 172.24.184.21=1 172.24.166.48=1 172.24.175.43=1 Thread 4 processed , missed 172.24.184.12=1 172.24.175.55=1 172.24.166.13=1 172.24.184.46=1 Thread 1 processed 3, missed Thread 2 processed 3, missed Thread 0 processed 3, missed Thread 3 processed 2, missed Thread 5 processed , missed Thread 6 processed , missed Thread 7 processed , missed Thread 8 processed , missed Thread 9 processed , missed Thread 10 processed , missed Thread 11 processed , missed Thread 12 processed , missed Thread 13 processed , missed Thread 14 processed , missed Thread 15 processed , missed Thread 16 processed , missed Thread 17 processed , missed Thread 18 processed , missed Thread 19 processed , missed
      Do I have to convert the hostnames to IP address first?Any thoughts on how to get it working fully please?

      Thanks
      Blackadder
        Looks like it DID work. You successfully pinged 12 hosts.

        To get the "verbose" output, run it like this:
        >ping_sweep2.pl -v

             Re:Do I have to convert the hostnames to IP address first?Any

        From the Net::Ping FM:
        $host can be either the hostname or the IP number of the remote host

        You should also be able to collapse some of the code like so (untested):

        ##Replace THIS code while (<DATA>) { chomp; print "$_ : "; my $ip_address = Win32::AdminMisc::gethostbyname($_); print "$ip_address\n"; push (@targets, $ip_address); } # Generate list of hosts to ping foreach my $target (@targets) { $RequestQ->enqueue ($target); } ## Replace with THIS code #### while (<DATA>) { chomp; print "Queuing ping for $_ : "; $RequestQ->enqueue $_ ; # Feed the NAME directly in }

            Earth first! (We'll rob the other planets later)

Re: Multi-threading ping of a list of hosts.....Again!
by BrowserUk (Patriarch) on Sep 20, 2004 at 11:31 UTC

    This "example code" is nothing more than a slight re-write of the code you posted at Threads problem.. It didn't work then, and it won't work now.

    Do you ever make any attempt to learn from the answers you recieve here? Or just simply use them to fulfil the job you are paid to do and ask a new question in the hope that someone will do your job for you the next time the problem comes up?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      Oh, no,....it did work then, Honestly Abigail. Well the pinging of mass host names did work with this script. But what didn't work was when I tried to adapt it so that it gathers share and folders sizes simultaneously. But then I got help from BrowserUk and by using WSH and multithreading the problem was solved.

      Sorry, I am a bit slow learner.

      I have spoken to Damian Conway in person 2 weeks ago – during his Aikido presentation - and having explained my trials and tribulations with Multithreading (I can hear most of you would saying 'trial and tribulation in everything Blackadder :-D' he informed that him and Larry Wall are working on Perl version 6 which will address most of short falls of multithreading in Perl. I asked about the reentry into Win32::OLE hash when multithreading and he informed that this will also be addressed. That’s all the information I managed to get from Damian. ...Just thought I share this with you,…..BTW: Congratulation to Larry Wall for his daughters wedding and I wish him well and speedy recovery.

      Blackadder
        Sorry (again),...I thouht the above post was from Abigale.

        Cheers
        Blackadder
        Sorry, I am a bit slow learner.

        A pre-requisite for learning, is attempting. Had you at least attempted to adapt one of the previous answers working code to your problem and then come back for help, it would have seemed less like you were asking for a canned solution.

        Perl version 6 which will address most of short falls of multithreading in Perl.

        Two problems:

        1. P6 is still at least a year away, as it has been for the past two (and more) years.
        2. I too once believed that P6 would be the saving grace of threaded Perl.

          Unfortunately, it appears that it's threading model will be firmly based on the same terminally broken underlying model (pthreads) as both p5 implementations.

          It also appears to me, as an interested, somewhat knowledgable but otherwise impotent external observer, that at least 1/2 of the design team of Parrot have an active agenda to ignore the requirements (and with it, the benefits) of the threading model of multitasking.

          I could be misreading the signs, and things could change, but I have given up my hopes of P6 being a truely cross-platform multi-tasking capable language.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: Multi-threading ping of a list of hosts.....Again!
by grantm (Parson) on Sep 20, 2004 at 22:07 UTC

    I have used fping in backticks and parsed the output from Perl. fping is a fast parallel ping utitlity and the man page even includes examples of calling it from Perl.

      Downloaded it but couldn't install it!!!.

      Extracted the downloaded Zip file, however there was no fping utility as such that that i can use from cmd or Perl script.

      The example Perl script included was calling for a &open2 file which did not exist....etc

      I think I will stick to a pure Perl solutions.

      Thanks
      Blackadder
Re: Multi-threading ping of a list of hosts.....with POE!
by kelan (Deacon) on Sep 25, 2004 at 14:20 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://392326]
Approved by pikus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2024-04-25 16:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found