0

我有一堆设备,我必须登录并在它们上运行一些命令。由于这需要时间并且有很多我想并行化任务,因此同时执行其中一些。我已经完成了,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。

4

1 回答 1

1

Thread::Queue在后台使用threads::shared,并且threads::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.pm, AnyEvent, POE...),甚至考虑使用传统的pipe+ fork

于 2013-09-11T20:07:31.590 回答