平时,要自动ssh到远程主机上做操作时,都要建立信任关系,这样在连接时,才不用输入密码。 就想不用建立信任关系的情况下,来自动ssh连接到远程主机做操作。可以用提供一个所要连接的远程主机列表来实现这个功能。

列表里提供了主机IP,用户,密码,格式如下:
192.168.0.1        root        123456
192.168.0.2        root        654321

    之前,有过一个自己写的难看的shell脚本,来实现抓取到远程主机的各种系统信息(monitor.sh,脚本见附件),通过Net::SCP::Expect模块来把这个脚本传到远程主机,再运行它,把所生成的日志报告再传回本地管理机上。这样来实现自动轮询抓取所有远程主机的系统信息到本地管理主机。

    之前,有考虑过使用 Net:SCP 模块来实现传输文件的功能,但发现它没有输入密码的功能,也就是说两台相连接的主机之间,必须建立信任关系。

    在perl里,有很多模块可以实现ssh连接远程主机做操作,以下是使用Net::SSH::Perl来实现的。



Perl脚本如下:

  1. use strict;
  2. use warnings;
  3. use Net::SCP::Expect;
  4. use Net::SSH::Perl

  5. open HOST_LIST, "Remote_host_list.txt" || die "can`t open this file\n";

  6. while(<HOST_LIST>){
  7.         my ($host,$user,$passwd) = split;
  8.         my $scpe = Net::SCP::Expect->new(host=>"$host",user=>"$user",password=>"$passwd",auto_yes=>"1",verbose=>"1",timeout=>"30");
  9.         $scpe->scp("monitor.sh","/root");

  10.         my %params = (
  11.                         protocal => '2,1',
  12.                         # debug => '1'
  13.                         );

  14.         my $ssh = Net::SSH::Perl->new($host,%params);
  15.         $ssh->login($user,$passwd);

  16.         $ssh->register_handler("stdout",sub{
  17.                         my($channel,$buffer) = @_;
  18.                         my $str = $buffer->bytes;
  19.                         if($str =~ /(.*)\[Y\/n\/\?\]/i){
  20.                                 $channel->send_data("y\n")
  21.                                 }}
  22.         );

  23.         $ssh->cmd("/bin/bash /root/monitor.sh");
  24.         $scpe->scp("$host:/root/*.log","/root")
  25. };

  26. close HOST_LIST;



遇到的问题:

1. 通配符 "*" 问题

发现,从local to remote时,$scpe->scp("/root/*.log","/root")不成功,只能具体指定一位文件名,如要多文件传输,只能一个一个的写,报错信息如下:
scp exited with non-success state: 256 at ./t.pl line 30

当 remote to local 时,$scpe->scp("$host:/root/*.log","/root")成功,可把.log的所有文件,都传到local本地。


2. 没法实现传输整个目录,建议使用rsync来实现。



用 Net::SSH::Perl 实现不用建信任关系 ssh连接操作-LMLPHP monitor.sh.txt  
09-21 04:37