我有一堆设备需要登录并在其上运行一些命令。由于需要时间并且有一大堆我想要并行化任务,所以同时做一些。我已经使用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。
答案 0 :(得分: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
。