2

私は決して perl やマルチスレッドの専門家ではありませんが、「やり方が間違っている」と確信しており、スレッド終了の警告が表示されないように変更する方法についてのガイダンスが必要です。

ご覧のとおり、このプログラムは引数 0 を読み取り、検索を行ってホスト名に関連付けられた各 IP アドレスを見つけ、次に各 IP をテストして ssh が実行されているかどうかを確認します。

このスクリプトの目的は、各ホストの tcp テストを生成し、最初に成功した tcp 接続を返すことです。

より信頼性が高く、睡眠を必要としないこれを行う方法を誰かが提案できますか?

use strict;
use warnings;
BEGIN {
    use Config;
    $Config{useithreads} or die('Recompile Perl with threads to run this program.');
}
use threads;
use IO::Socket::INET;
$| = 1;

unless($ARGV[0]){ die("error please use argument")}

my $timeoutval=3;
my $testHost=$ARGV[0];
my $dlquery=`dig $testHost | grep 'IN A'`;
my $SUCCESS=0;

sub testSSHhost {
    my $fqdn = shift;
    my $socket = new IO::Socket::INET (
            PeerHost => $fqdn,
            PeerPort => '22',
            Proto => 'tcp',
            Timeout => $timeoutval,
    ) or return "ERROR in Socket Creation : $!\n";

    my $tcpData = <$socket>;
    $socket->close();
    if ($tcpData && $tcpData=~/SSH/){
            print "$fqdn\n";
            $SUCCESS=1;
            exit(0);
    }
    return $fqdn;
}

my @threads;
for my $line (split(/\n/,$dlquery)){
    my @linesplit=split(/ /,$line);
     $linesplit[0]=~s/\.$//;
     $linesplit[0]=~s/ *//g;
     my $t = threads->new(\&testSSHhost, $linesplit[0]);
     push(@threads,$t);
}

while (!$SUCCESS){sleep 0.3}

本当に私が避けようとしているのは、「2 つのスレッドの実行中にスレッドが終了した」ということです。エラーメッセージまたは「セグメンテーション違反」メッセージ

4

2 に答える 2

2

このようなもの(テストされていません!):

use Modern::Perl;
use threads;
use Thread::Queue;
use IO::Socket::INET;
$| = 1;

my $testHost = $ARGV[0];
my $dlquery  = `dig $testHost | grep 'IN A'`;
my $config   = { NUMBER_OF_THREADS => 5 };      #how many threads you gonna use?

my $queue           = Thread::Queue->new;
my $queue_processed = Thread::Queue->new;

for my $line ( split( /\n/, $dlquery ) ) {
    my ($ip) = split( / /, $line );
    $ip =~ s/\.$//;
    $ip =~ s/ *//g;

    $queue->enqueue($ip);
}

foreach my $thread_id ( 1 .. $config->{NUMBER_OF_THREADS} ) {

    $queue->enqueue(undef);
    my $thread = threads->create( \&testSSHhost() )->detach();
}

while ( $queue->pending() ) {

    my $result = $queue_processed->dequeue();

    if ( $result->{status} ) {

        say $result->{ip};
    }
}

sub testSSHhost {

    while ( my $fqdn = $queue->dequeue() ) {

        my $status = 0;

        my $socket = new IO::Socket::INET(
            PeerHost => $fqdn,
            PeerPort => 22,
            Proto    => 'tcp',
            Timeout  => 3,
        ) or return "ERROR in Socket Creation : $!\n";

        my $tcpData = <$socket>;
        $socket->close();
        if ( $tcpData && $tcpData =~ /SSH/ ) {

            $status = 1;
        }

        $queue_processed->enqueue( { ip => $fqdn, status => $status, } );
    }

    return 0;
}
于 2012-06-22T15:28:31.463 に答える
0

キューで実現できます: http://search.cpan.org/dist/Thread-Queue/lib/Thread/Queue.pm

スレッドを生成する前に、キューを作成し、スレッドが成功した IP アドレスをそこにプッシュできるようにします。次に、何かがポップアップするまで、親プロセスはデキューでブロックされます。

于 2012-06-22T14:16:36.717 に答える