平时,要自动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脚本如下:
- use strict;
- use warnings;
- use Net::SCP::Expect;
- use Net::SSH::Perl
- open HOST_LIST, "Remote_host_list.txt" || die "can`t open this file\n";
- while(<HOST_LIST>){
- my ($host,$user,$passwd) = split;
- my $scpe = Net::SCP::Expect->new(host=>"$host",user=>"$user",password=>"$passwd",auto_yes=>"1",verbose=>"1",timeout=>"30");
- $scpe->scp("monitor.sh","/root");
- my %params = (
- protocal => '2,1',
- # debug => '1'
- );
- my $ssh = Net::SSH::Perl->new($host,%params);
- $ssh->login($user,$passwd);
- $ssh->register_handler("stdout",sub{
- my($channel,$buffer) = @_;
- my $str = $buffer->bytes;
- if($str =~ /(.*)\[Y\/n\/\?\]/i){
- $channel->send_data("y\n")
- }}
- );
- $ssh->cmd("/bin/bash /root/monitor.sh");
- $scpe->scp("$host:/root/*.log","/root")
- };
- 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来实现。
monitor.sh.txt