Multithreading Perl多线程-第一个线程成功时退出

Multithreading Perl多线程-第一个线程成功时退出,multithreading,perl,Multithreading,Perl,我绝对不是perl或多线程方面的专家,但我确信我“做得不对”,需要一些关于如何修改它的指导,以免收到线程退出警告 如您所见,此程序读取参数0,进行查找以查找与主机名关联的每个IP地址,然后测试每个IP以查看ssh是否正在运行 此脚本的目的是为每个主机生成一个tcp测试,并返回第一个成功的tcp连接 有谁能建议一种更可靠、不需要睡眠的方法吗 use strict; use warnings; BEGIN { use Config; $Config{useithreads} or d

我绝对不是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}
使用严格;
使用警告;
开始{
使用配置;
$Config{useithreads}或die('使用线程重新编译Perl以运行此程序');
}
使用线程;
使用IO::Socket::INET;
$| = 1;
除非($ARGV[0]){die(“错误请使用参数”)}
我的$timeoutval=3;
my$testHost=$ARGV[0];
my$dlquery=`dig$testHost|grep'在'`;
我的$SUCCESS=0;
子测试SSHHOST{
my$fqdn=班次;
my$socket=新IO::socket::INET(
PeerHost=>$fqdn,
PeerPort=>'22',
Proto=>“tcp”,
超时=>$timeoutval,
)或返回“创建套接字时出错:$!\n”;
我的$tcpData=;
$socket->close();
如果($tcpData&&$tcpData=~/SSH/){
打印“$fqdn\n”;
$SUCCESS=1;
出口(0);
}
返回$fqdn;
}
我的@threads;
对于我的$行(拆分(/\n/,$dlquery)){
my@linesplit=拆分(/,$line);
$linesplit[0]=~s/\.$/;
$linesplit[0]=~s/*//g;
my$t=threads->new(\&testSSHhost,$linesplit[0]);
推送(@threads,$t);
}
而(!$SUCCESS){sleep 0.3}
实际上,我试图避免的是“一个线程在两个线程运行时退出。”错误消息
或者“分段错误”消息

您可以通过QUES实现:

在生成线程之前,创建一个队列,然后让线程将成功的IP地址推送到队列中。然后父进程将阻止退出队列,直到有东西弹出。

类似这样的(未测试!):

使用Modern::Perl;
使用线程;
使用线程::队列;
使用IO::Socket::INET;
$| = 1;
my$testHost=$ARGV[0];
my$dlquery=`dig$testHost|grep'在'`;
我的$config={线程数=>5}#你要用多少线?
my$queue=线程::队列->新建;
my$queue_processed=线程::队列->新建;
对于我的$行(拆分(/\n/,$dlquery)){
我的($ip)=分割(/,$line);
$ip=~s/\.$/;
$ip=~s/*//g;
$queue->enqueue($ip);
}
foreach my$thread_id(1..$config->{NUMBER_OF_THREADS}){
$queue->enqueue(未定义);
my$thread=threads->create(\&testSSHhost())->detach();
}
而($queue->pending()){
my$result=$queue_processed->dequeue();
如果($result->{status}){
说$result->{ip};
}
}
子测试SSHHOST{
而(我的$fqdn=$queue->dequeue()){
我的$status=0;
my$socket=新IO::socket::INET(
PeerHost=>$fqdn,
皮尔波特=>22,
Proto=>“tcp”,
超时=>3,
)或返回“创建套接字时出错:$!\n”;
我的$tcpData=;
$socket->close();
如果($tcpData&&$tcpData=~/SSH/){
$status=1;
}
$queue_processed->enqueue({ip=>$fqdn,status=>$status,});
}
返回0;
}

任何人都可以提供一个简单的示例,说明如何使用队列执行此操作。我已经看完了文件,但什么也没有回来。你想从一个成功的线程中锁定队列,然后每隔一个线程退出一次吗?gangabass在几分钟前提供了更多详细信息。这是一个很好的建议,但不是重点-如果OP在第一次退出队列后仅
exit()
s,他将遭受相同的错误。请使用
strict
warnings
。在开始块中检查
useithreads
,以便在
使用线程之前进行检查。(我知道,我知道,
perlthrut
在这里有误导性。)IO::Socket::INET可靠地返回
$@
中的错误,而不是
$-悲伤/奇怪但真实
$fqdn
不需要作为PeerHost参数引用
$SUCCESS
不是
share()
d,因此您的主线程将永远看不到更新。每个人都是批评家,但往往值得倾听。
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;
}