给Threads他们自己生成的Expect:Unsupported ref type:GLOB

时间:2013-09-11 16:35:37

标签: multithreading perl fork expect

我有一堆设备需要登录并在其上运行一些命令。由于需要时间并且有一大堆我想要并行化任务,所以同时做一些。我已经使用Net::Telnet完成了它,但我现在必须使用Expect.pm

在我的主线程中,我使用名为@FW的hashrefs填充\%host数组:

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

push(@FW, \%host);

然后我做了一个线程池/队列我从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();
}

我已经阅读过CPAN,我必须给每个线程产生自己的预期,但我做错了什么?我试图通过相同的哈希传递对象以及其他参数继承人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"); 

(我没看到那个印刷声明)

同样,这个问题不是关于我使用Expect(有效),而是关于如何在线程中使用Expect。

1 个答案:

答案 0 :(得分:1)

Thread::Queue使用threads::sharedthreads::shared不支持所有Perl数据类型。特别是看起来不支持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 $@;
}

使用线程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.

除了不使用线程,我认为你不能做任何事情,而是使用基于事件的机制(Event.pmAnyEventPOE ...)或者甚至考虑使用传统的pipe + fork