简体   繁体   English

给线程自己生成的期望:不支持的引用类型:GLOB

[英]Give Threads their own spawned Expect: Unsupported ref type: GLOB

I have a bunch of devices I have to logon to and run a few commands on them. 我有一堆设备必须登录并在其中运行一些命令。 As it takes time and there are a bunch of them I want to parallelise the task, do a few of them at the same time. 由于需要时间,并且有很多我想并行执行任务,因此请同时执行其中的一些任务。 I've done it with Net::Telnet however I have to use Expect.pm now. 我已经用Net::Telnet完成了,但是我现在必须使用Expect.pm

In my main thread I fill up the @FW array with hashrefs called \\%host thusly: 在我的主线程中,我用称为\\%host@FW填充了@FW数组:

my $EXPECT =  new Expect();
$EXPECT->spawn("ssh $username\@$ip");
$host{'expect'} = $EXPECT;

push(@FW, \%host);

Then I do a thread pool/queue i nicked from perlmonks which I've used for a few other things so I know that approach does work however I'm getting the error (check my comment in the code below) 然后我做了一个线程池/队列,这个线程池/队列是我从perlmonks昵称的,我已经将其用于其他一些事情,所以我知道该方法确实有效,但是我遇到了错误(请在下面的代码中查看我的评论)

sub getWorkItems {
    my $host = pop(@FW);
    return $host ? $host : undef;
}

our $THREADS = 3;
my $Qwork    = new Thread::Queue;
my $Qresults = new Thread::Queue;

my @pool = map {
    threads->create(\&worker, $Qwork, $Qresults)
} 1 .. $THREADS;

while (my $workItem = getWorkItems()) { # ERROR HERE: Unsupported ref type: GLOB
    $Qwork->enqueue($workItem);
}
$Qwork->enqueue((undef) x $THREADS);

sub worker {
    my $tid = threads->tid;
    my ($Qwork, $Qresults) = @_;
    while (my $host = $Qwork->dequeue()) {
        backup($host->{'expect'}, $host->{'hostname'}, $host->{'ip'}, $host->{'username'}, $host->{'password'});
    }
    $Qresults->enqueue(undef); ## Signal this thread is finished
}

for (1 .. $THREADS) {
    while (my $result = $Qresults->dequeue()) {
        print "T$_  $result", "\n";
    }
}

foreach (@pool) {
    $_->join();
}

I've read on CPAN that I have to give each thread its own spawned expect, but what am I doing wrong? 我在CPAN上阅读过,我必须给每个线程一个自己产生的期望,但是我在做什么错呢? I'm trying to pass the object via the same hash along with the other arguments heres how the backup sub begins: 我试图通过相同的哈希值以及其他参数来传递对象,以下是backup子程序的开始方式:

sub backup {
    my ($EXPECT, $hostname, $ip, $username, $password) = @_;

    print "$EXPECT, $hostname, $ip, $username, $password\n";

    my $auth = $EXPECT->expect(3, -re => "authenticity of host"); 

(I don't see that print statement) (我看不到该打印声明)

Again, this question is not about my use of Expect (that works), it's about how to use Expect in threads. 再次,这个问题不是关于我对Expect(有效)的使用,而是关于如何在线程中使用Expect。

Thread::Queue uses threads::shared under the hood, and threads::shared does not support all Perl data types. Thread::Queue使用threads::shared ,而threads::shared不支持所有Perl数据类型。 Especially it looks like GLOBs are not supported. 特别是看起来不支持GLOB。

use threads;
use threads::shared;

my $foo :shared;
for my $val (1, "foo", qr{regexp}, ["array"], {"ha"=>"sh"}, \*STDOUT, sub { }) {
    eval { $foo = shared_clone($val) };
    warn "Setting to $val failed: $@" if $@;
}

With a threaded perl 5.18.1 I get: 使用线程Perl 5.18.1,我得到:

Setting to (?^:regexp) failed: Unsupported ref type: REGEXP at shared.pl line 8.
Setting to GLOB(0x80184e798) failed: Unsupported ref type: GLOB at shared.pl line 8.
Setting to CODE(0x801aa78e8) failed: Unsupported ref type: CODE at shared.pl line 8.

I don't think you can do anything about it, other than not using threads, but instead using event-based mechanisms ( Event.pm , AnyEvent , POE ...) or even think about using traditional pipe + fork . 除了不使用线程,我不认为您可以做任何事情,而是使用基于事件的机制( Event.pmAnyEventPOE ...),甚至考虑使用传统的pipe + fork

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM