Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Need help with Perl multi threading

by Corion (Pope)
on Jan 25, 2012 at 19:03 UTC ( #949946=note: print w/ replies, xml ) Need Help??


in reply to Need help with Perl multi threading

Please show the code and data that does "not work" for you. Please make it self-contained and about 20 to 25 lines long. Thank you.


Comment on Re: Need help with Perl multi threading
Re^2: Need help with Perl multi threading
by ashok.g (Beadle) on Jan 25, 2012 at 19:47 UTC
    Hi Corion,

    Thanks for your reply. Main code:
    #!/usr/bin/perl use threads; use strict; use warnings; use Net::SSH::Expect; require 'total.pl'; my @servers = ('192.168.0.18','192.168.0.19','192.168.0.20'); my @process = ('testing','b','c'); my @threads; my $output; my $res; foreach my $host ( @servers ) { my $png = `ping -c1 $host`; if ( $png =~ /64 bytes/ ) { my $user= 'netcool'; my $ssh = &SSH_Reference($host,$user); $ssh->run_ssh(); eval {$res=$ssh->read_all(); }; if ( !$@ && $res !~ /\(yes\/no\)/ && $res !~ m/password/ ) { print "\nLogged in to $host\n"; foreach my $proc ( @process ) { push (@threads, threads->new(\&Process_Output, $ss +h, $proc )); while ( my $thread = shift @threads ) { $output=$thread->join(); #print @output; if ( $output =~ m/$proc/ ) { print "\t$proc is runn +ing\n"; } else { print "\t$proc is not +running\n"; } } } $ssh->close(); } else { print "Unable to SSH to $host\n"; } } else { print "\nUnable to ping to Host: $host\n"; } }
    total.pl:
    use Config::General; use Tie::IxHash; use Net::SNMP; sub SSH_Reference() { ($host,$user)=@_; #print "$host---$user--\n"; #($host,$user)= @_; $ssh = Net::SSH::Expect->new ( host => $host, user => $user, timeout=>10, raw_pty => 1 ); return $ssh; } sub Process_Output() { $ssh = shift; $process = shift; #( $ssh, $process ) = @_; $output; $ssh->eat($ssh->peek(0)); $ssh->send("ps -ef | grep $process | grep -v 'grep'"); while ( defined ($line = $ssh->read_line(2)) ) { next if ( $line =~ m/grep/ ); $output .= "$line"; } $ssh->eat($ssh->peek(0)); return $output; } 1;
    And the output is:
    perl some.pl Logged in to 192.168.0.18 Use of uninitialized value in pattern match (m//) at some.pl line 33. testing is not running Thread 2 terminated abnormally: SSHConnectionAborted at total.pl line +25 Use of uninitialized value in pattern match (m//) at some.pl line 33. b is not running Thread 3 terminated abnormally: SSHConnectionAborted at total.pl line +25 Use of uninitialized value in pattern match (m//) at some.pl line 33. c is not running Logged in to 192.168.0.19 Segmentation fault
    Please suggest

    Thanks,
    Ashok

      The first, most obvious problem is that you did not use warnings; use strict;

      I see undeclared variables and other weird stuff. What's "$output;" all by itself in the middle of the function supposed to do anyways?

        Ok. I have modified the code and new output now.

      I suspect your main problem is that you're trying to use the same instance of the SSH connection in all threads.  Creating a new thread doesn't automagically also create a new independent duplicate of the connection (socket, server-side process, and all), so the SSH will probably get mildly confused when multiple clients are talking simultaneously on the same line...

      Sorry to be rude, but you really don't seem to have a clue what you are doing.

      This is a completely redundant use of threading:

      push (@threads, threads->new(\&Process_Output, $ssh, $proc )); while ( $thread = shift @threads ) { @output=$thread->join(); }

      You create a thread and push its handle onto @threads. You then immediately shift that handle off of the array and join it.

      1. There is no point in using an array here, because it will only ever contain at most one handle.
      2. Which makes using the while loop redundant because it will only ever iterate once.

        It is exactly equivalent to:

        $thread = threads->new(\&Process_Output, $ssh, $proc ); if( $thread ) { @output = $thread->join(); }

        Which is equivalent to :

        $thread = threads->new(\&Process_Output, $ssh, $proc ); @output = $thread->join();

        Which is exactly equivalent to this:

        @output = threads->new(\&Process_Output, $ssh, $proc )->join();

        Which is exactly equivalent to:

        @output = Process_Output( $ssh, $proc );

        Except that the latter will work. (Of course, it won't speed things up. But neither will what you have now.) But it will work.

      The reason your code is crashing is because you are creating an instance of Net::SSH::Expect in one thread, and trying to use it in another.

      Why? Why not create the object in the thread where you are going to use it?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      The start of some sanity?

        Thanks for your explanation!

        So, you mean to say keep the thread that will do all like creating a SSH reference, calling function and what not for each server....?

        This is exactly what I started with but I thought thread is having some problems with SSH (a dumb guess) and ignored that.

        I will try that and will post you my findings.

        Thanks,
        Ashok.
        Now this code:
        #!/usr/bin/perl use threads; use strict; use warnings; use Net::SSH::Expect; require 'total.pl'; my @servers = ('192.168.0.18','192.168.0.19','192.168.0.20'); my @process = ('testing','b','c'); my @threads; my $output; my $res; my $final; #@output = threads->new(\&Process_Output, $ssh, $proc )->join(); foreach my $host ( @servers ) { threads->new(\&process, $host )->join(); } sub process() { my $host = shift; my $png = `ping -c1 $host`; if ( $png =~ /64 bytes/ ) { my $user= 'netcool'; my $ssh = &SSH_Reference($host,$user); $ssh->run_ssh(); eval {$res=$ssh->read_all(); }; if ( !$@ && $res !~ /\(yes\/no\)/ && $res !~ m/password/ ) { print "\nLogged in to $host\n"; foreach my $proc ( @process ) { #push (@threads, threads->new(\&Process_Output, $s +sh, $proc )); $output=&Process_Output($ssh, $proc ); #print @output; if ( $output =~ m/$proc/ ) { print "\t$proc is runn +ing\n"; } else { print "\t$proc is not +running\n"; } } $ssh->close(); } else { print "Unable to SSH to $host\n"; } } else { print "\nUnable to ping to Host: $host\n"; } }
        produces this output:
        perl some.pl Unable to SSH to 192.168.0.18 Unable to SSH to 192.168.0.19 Unable to SSH to 192.168.0.20
        Now again back to the stage where I have started my script....

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://949946]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2014-11-26 05:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (162 votes), past polls