- 论坛徽章:
- 0
|
本帖最后由 liudashang 于 2019-03-16 09:58 编辑
use strict;
use threads;
use Thread::Semaphore;
use Net::Telnet::Cisco;
my $start = time();
my @host = ("192.168.0.2","192.168.0.3","192.168.0.4","192.168.0.5","192.168.0.6");
my @threads;
my $count = 0;
my $signal = Thread::Semaphore->new(); #测试同步时,请注释掉此行
for my $host (@host) {
$threads[$count] = threads->create(\&switch,$host); #测试同步时,请注释掉此行
$count++; #测试同步时,请注释掉此行
#&switch($host); #测试同步时,请去掉注释!!!
}
for my $th (@threads) { #测试同步时,请注释掉此行
$th->join(); #测试同步时,请注释掉此行
} #测试同步时,请注释掉此行
my $endtime = time() - $start;
print "\n$endtime\n";
sub switch{
my $host = shift;
my $s = Net::Telnet::Cisco->new($host);
$s->login(Name => 'cisco',Password => 'cisco');
my @output = $s->cmd('show version');
$signal->down(); #测试同步时,请注释掉此行
print '*#*' x 30;
print @output;
print '=&=' x 30;
$signal->up(); #测试同步时,请注释掉此行
$s->close;
}
=========================另一种方法======================
使用coro:
use IO::Socket::Telnet;
use strict;
use AnyEvent;
use Coro;
use Coro::AnyEvent;
use Coro::Socket;
my $start = time;
my @host = ("192.168.1.112","192.168.1.113","192.168.1.114","192.168.1.115","192.168.1.116",
"192.168.1.117","192.168.1.118",,"192.168.1.253","192.168.1.119","192.168.1.120","192.168.1.121",
"192.168.1.122","192.168.1.123","192.168.1.124","192.168.1.125","192.168.1.126",
"192.168.1.127","192.168.1.128","192.168.1.129","192.168.1.130","192.168.1.131");
my @coro;
for my $host (@host) { #此处到foreach循环结束都可以照搬照抄
push @coro, async {
my $socket = Coro::Socket->new_from_fh
(IO::Socket::Telnet->new(
PeerAddr => $host,
Timeout => 5
)
);
&doit($host,$socket); #具体多线程操作均在此方法内
return;
}
}
foreach (@coro) {
print "joining\n"; #验证多线程使用,可以删除
$_->join;
print "joined\n"; #验证多线程使用,可以删除
}
sub doit {
my $result; #负责收集telnet服务端返回的信息
my $host = shift;
my $socket = shift;
my $s;
eval {$s = &read($socket);}; #IO::Socket::Telnet模块本身缺少异常处理,此处
#eval的作用是检测服务器连接超时并报错。考虑到多
#线程,不建议调用die中断程序
return print "Can't connect $host\n" if $@;
$result .= $s;
if ($s =~ /Username:/) { #猜测交换机的telnet密码
$socket->send("user\n");
$s = &waitfor($socket,'Password: $');
$result .= $s;
$socket->send("password\n");
} else {
$socket->send("password\n");
}
$s = &waitfor($socket,'.+>$');
=pod
$result .= $s;
$socket->send("sh int status\n");
$s = &read($socket);
$result .= $s;
=cut
$socket->send("sh cdp nei de\n");
$s = &read($socket);
$result .= $s;
print $result."\n";
=pod
while (1) {
my $buffer;
$socket->send(scalar <>);
print &read($socket);
}
=cut
$socket->close;
}
print time-$start;
sub read { #对recv封装,实现serve回传数据的正常交互
my $self = shift;
my $start;
while (1) {
$self->recv(my $x, 4096);
next if !$x;
$start .= $x;
last if $x =~ /(<.+>|\[.+\]|.+>|.+#)$/;
$self->send(' ') if $x =~ /More/;
last if $x =~ /(Password: ?|Username: ?)/;
}
return $start;
}
sub waitfor { #简单模仿Net::Telnet中的waitfor方法
my $self = shift;
my $regx = shift;
my $start;
while (1) {
$self->recv(my $x, 4096);
next if !$x;
$start .= $x;
last if $x =~ /$regx/;
$self->send(' ') if $x =~ /More/;
}
return $start;
}
|
|