2011-11-14 5 views
4

J'écris un script Perl simple qui devrait exécuter d'autres scripts Perl simultanément. Je ne sais pas comment faire attendre le programme principal pour l'exécution de threads. Le sommeil n'est pas une solution appropriée à cause de nombreuses raisons. Ceci est mon script « principal »:Perl multithread et foreach

#!/usr/bin/perl 
use threads; 
main: 
{ 
    if ($#ARGV == -1) { usage(); exit(1); } 
    my $hostname = $ARGV[0]; 
    my $thrssh = threads ->create(\&ssh, $hostname); 
    my $thrdns = threads ->create(\&dns, $hostname); 
    my $thrping = threads ->create(\&ping, $hostname); 
    my $thrsmtp = threads ->create(\&smtp, $hostname); 
    my $thrproxy = threads ->create(\&proxy, $hostname); 
} 
sub ssh { 
    threads->detach(); 
    my $hostname = @_; 
    #print "SSH\n"; 
    #LAUNCH SSH SCRIPT 
} 
#OTHER SUBROUTINES... 
sub proxy { 
    threads->detach(); 
    my $hostname = @_; 
    #print "PROXY\n"; 
    #LAUNCH PROXY SCRIPT 
} 

Si je tente de lancer ce script la première chose que je peux remarquer est que les impressions sont « séquentiel », je pensais que le texte a été foiré mais peut-être Imprimer est exclusive Je ne t sais. Le problème principal est que les deux derniers sous-programmes n'ont pas le temps d'être exécutés.

SSH 
DNS 
PING 
Perl exited with active threads: 
2 running and unjoined 
0 finished and unjoined 
0 running and detached 

Si je rejoindre au lieu de détachez les sous-routines deviennent « séquentielle », par exemple, si je mets un sommeil sous ssh autres threads attendront avant de commencer. Je veux qu'ils soient parallèles et que le programme principal se ferme SEULEMENT quand tous les threads sont terminés, n'importe quelle aide?

En fait, j'ai une autre question, si je dois exécuter plusieurs threads dans un foreach quand je suis supposé les rejoindre? à savoir:

my $thrssh; 
foreach $mynode ($nodeset->get_nodelist) { 
    #... 
    $thrssh = threads ->create(\&ssh, $port, $hostname); 
    #... 
} 
$thssh->join(); 

Est-ce exact?

Répondre

9

Vous devez join tous vos threads à partir du thread principal après qu'ils ont tous été démarrés. Ne pas detatch si vous ne voulez pas que l'interpréteur quitte pendant que les threads sont encore en cours d'exécution.

... 
my $thrssh = threads ->create(\&ssh, $hostname); 
my $thrdns = threads ->create(\&dns, $hostname); 
... 
$thrssh->join(); 
$thrdns->join(); 
... 

En ce qui concerne votre édition: non, ce n'est pas correct. Vous devez conserver une référence à chaque thread que vous créez, sinon vous ne pouvez pas les joindre.

faire quelque chose comme:

my @thrs; 
foreach $mynode ($nodeset->get_nodelist) { 
    #... 
    $thrssh = threads ->create(\&ssh, $port, $hostname); 
    push @thrs, $thrssh; 
    #... 
} 
$_->join() for @thrs; 
+0

Il était parfait :) Merci! – raz3r

+0

Mis à jour après votre modification. – Mat

+0

J'ai eu la même idée et en fait, ça marche! Merci encore! – raz3r