zoukankan      html  css  js  c++  java
  • Perl脚本通过Expect登陆多台设备批量执行命令并Log

    本例子尝试使用Perl脚本借助Expect模块实现如下目的:

    • 登陆多台设备

    设备登陆信息按如下格式存放于文件中。

    $ cat hosts.txt
    192.168.30.7:node1:telnet:bee1:123456
    192.168.30.66:node2:ssh:bee2:123456
    
    • 在每台设备上批量执行命令

    要执行的命令集合按如下格式存放于文件中。

    $ cat cmds.txt
    date
    w
    ifconfig
    more mylog.txt
    
    • Perl脚本实现,使用了Expect模块

    借助Expect模块实现登陆,执行命令,捕获命令回显,取日志,自动回复more分页,ping探测主机等功能。
    脚本中的语句形式可供参考。

    • 脚本如下:
    #! /usr/bin/perl
    
    #安装模块
    #cpan
    #install Expect
    #install Net::Ping
    #perl -MCPAN -e "install autodie"
    
    use utf8;
    use Expect;
    use autodie;
    use Net::Ping;
    
    #0为关闭本地回显
    #$Expect::Log_Stdout=0;
    $ENV{TERM}="xterm";
    #不进行缓冲直接进文件
    #$|=1;
    
    #cmds.txt的文件格式:
    #一行一条命令
    my @cmds;
    my $cmds_file="./cmds.txt";
    open CMDS,"<",$cmds_file or die "Can't open file $cmds_file: $!
    ";
    print "commands to run: 
    ";
    while(<CMDS>){
        print "$_";
        chomp;
        push @cmds,$_;
    }
    close CMDS;
    print "=============================
    ";
    
    mkdir 'log' unless -e 'log';
    chomp(my $now=`date +%y%m%d`);
    my $exp=Expect->new;
    #$exp->raw_pty(1);
    
    #hosts.txt的文件格式:
    #IPv4地址:主机名:登陆方式(ssh/telnet):用户名:密码
    my $hosts_file="./hosts.txt";
    open HOSTS,"<",$hosts_file or die "Can't open file $hosts_file: $!
    ";
    while(<HOSTS>){
        chomp;
        @host=split /:/;
        if(&ping_host(@host)){
            &login_host(@host);
        }
    }
    close HOSTS;
    print "Loging finished!
    ";
    
    #子程序
    sub login_host{
        print "login to $_[1]($_[0])...
    ";
        my $user=$_[3];
        my $passwd=$_[4];
        my $ahost=$_[1];
        
        if($_[2] =~ /ssh/i){
            $exp=Expect->spawn("ssh -l $user $_[0]") or die "Can't login to $_[1]($_[0]): $!
    ";
            $exp->expect(3,
                [ #使用正则来表达包含关系
                    qr/connectings(yes/no)?/i,
                    sub {
                            my $self=shift;
                            $self->send("yes
    ");
                            exp_continue;
                    }
                ],
                [
                    qr/password:/i,
                    sub {
                            my $self=shift;
                            $self->send("$passwd
    ");
                            exp_continue_timeout;
                    }
                ]
            );
            #取log
            $exp->log_file("log/$_[1]-$now.log", "w");
            $exp->send("
    "); 
            
            foreach (@cmds){
                $exp->send("$_
    ");
                $exp->expect(2,
                    [ #使用正则来表达包含关系
                        qr/[>#$]/,
                        sub {
                            my $self=shift;
                            $self->send("
    ");
                            exp_continue_timeout;
                        }
                    ],
                    [
                        qr/--More--/i,
                        sub {
                            my $self=shift;
                            $self->send(" ");
                            exp_continue;
                        }
                    ]
                );
            }
            #关闭log
            $exp->log_file(undef);
            #退出登陆
            $exp->send("exit
    ") if ($exp->expect(undef,'-re' => '[>#$]')); #undef是痴等
            print "
    Logout from $_[1]($_[0])
    ";
        }else{
            $exp=Expect->spawn("telnet $_[0]") or die "Can't login to $_[1]($_[0]): $!
    ";
            $exp->expect(30,
                [ #使用正则来表达包含关系,否则就是精确匹配
                    qr/$ahost login:/i,
                    sub {
                            my $self=shift;
                            $self->send("$user
    ");
                            exp_continue;
                    }
                ],
                [
                    qr/Password:/i,
                    sub {
                            my $self=shift;
                            $self->send("$passwd
    ");
                            exp_continue_timeout;
                    }
                ]
            );
            #取log
            $exp->log_file("log/$_[1]-$now.log", "w");
            $exp->send("
    "); 
            
            foreach (@cmds){
                $exp->send("$_
    ");
                $exp->expect(2,
                    [ #使用正则来表达包含关系,否则就是精确匹配
                        qr/[>#$]/,
                        sub {
                            my $self=shift;
                            $self->send("
    ");
                            exp_continue_timeout;
                        }
                    ],
                    [
                        qr/--More--/i,
                        sub {
                            my $self=shift;
                            $self->send(" ");
                            exp_continue;
                        }
                    ]
                );
            }
            #关闭log
            $exp->log_file(undef);
            #退出登陆
            $exp->send("exit
    ") if ($exp->expect(undef,'-re' => '[>#$]')); #undef是痴等
            print "
    Logout from $_[1]($_[0])
    ";
        }
    }
    
    sub ping_host{
        $p=Net::Ping->new("icmp");
        if($p->ping($_[0])){
            print "$_[1]($_[0]) is alive
    ";
            return 1;
        }else{
            print "$_[1]($_[0]) is die
    ";
            return 0;
        }
    }
    
  • 相关阅读:
    https authorization basic
    第二十一章 单例模式
    第十九章 组合模式
    第十八章 备忘录模式
    第十七章 适配器模式
    第十六章 状态模式
    新博客~
    CF922D Robot Vacuum Cleaner
    BZOJ1767 [CEOI2009]harbingers
    树的直径学习笔记
  • 原文地址:https://www.cnblogs.com/cerana/p/11331556.html
Copyright © 2011-2022 走看看