SSH 的 Bash/Expect 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19101879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:16:02  来源:igfitidea点击:

Bash/Expect Script for SSH

bashsshexpect

提问by minorix

I am new to expect and scripting in general. I am trying to make a few scripts to make my life a bit easier when pulling network device configurations. I managed to create a basic expect script to SSH to a device and save the configuration.

我是新手,一般来说都是脚本编写的。我正在尝试编写一些脚本,以便在提取网络设备配置时让我的生活更轻松一些。我设法创建了一个基本的 expect 脚本以通过 SSH 连接到设备并保存配置。

I want to expand upon this and allow the script to connect to a number of IP addresses instead of just one like I have right now. I have a file named list.txtwith a few different IP addresses with each IP on a separate line.

我想对此进行扩展,并允许脚本连接到多个 IP 地址,而不是像我现在那样只连接一个。我有一个list.txt用几个不同 IP 地址命名的文件,每个 IP 都在单独的一行上。

What would I need to do to have the expect script connect to each of these IP addresses and perform the rest of the tasks in the script as well?

我需要做什么才能让 expect 脚本连接到每个 IP 地址并执行脚本中的其余任务?

Here is the Expect script I have so far:

这是我到目前为止的 Expect 脚本:

#!/usr/bin/expect -f
#Tells interpreter where the expect program is located.  This may need adjusting according to
#your specific environment.  Type ' which expect ' (without quotes) at a command prompt
#to find where it is located on your system and adjust the following line accordingly.
#
#
#Use the built in telnet program to connect to an IP and port number
spawn ssh 192.168.1.4 -l admin
#
#The first thing we should see is a User Name prompt
#expect "login as:"
#
#Send a valid username to the device
#send "admin"
#
#The next thing we should see is a Password prompt
expect "Password:"
#
#Send a vaild password to the device
send "password\n"
#
#If the device automatically assigns us to a priviledged level after successful logon,
#then we should be at an enable prompt
expect "Last login:"
#
#Tell the device to turn off paging
#
#After each command issued at the enable prompt, we expect the enable prompt again to tell us the
#command has executed and is ready for another command
expect "admin@"
#
#Turn off the paging
send "set cli pager off\n"
#
#Show us the running configuration on the screen
send "show config running\n"
#
# Set the date.
set date [timestamp -format %C%y%m%d]
#
#Test output sent to file with a timestamp on end
#-noappend will create a new file if one already exists
log_file -noappend /home/test.cfg$date
#
expect "admin@"
#
#Exit out of the network device
send "exit\n"
# 
#The interact command is part of the expect script, which tells the script to hand off control to the user.
#This will allow you to continue to stay in the device for issuing future commands, instead of just closing
#the session after finishing running all the commands.`enter code here`
interact

Do I need to integrate this with a Bash script? If so, is it possible to read one line of the list.txtfile, use that as the IP/host variable and then read the next and repeat?

我需要将它与 Bash 脚本集成吗?如果是这样,是否可以读取list.txt文件的一行,将其用作 IP/主机变量,然后读取下一行并重复?

回答by glenn Hymanman

I would do this (untested):

我会这样做(未经测试):

#!/usr/bin/expect -f

set logfile "/home/text.cfg[clock format [clock seconds] -format %Y%m%d]"
close [open $logfile w]         ;# truncate the logfile if it exists

set ip_file "list.txt"
set fid [open $ip_file r]

while {[gets $fid ip] != -1} {

    spawn ssh $ip -l admin
    expect "Password:"
    send "password\r"

    expect "admin@"
    send "set cli pager off\r"

    log_file $logfile
    send "show config running\r"

    expect "admin@"
    log_file 

    send "exit\r"
    expect eof

}
close $fid

Notes:

笔记:

  • I removed all your comments for brevity
  • use \rto simulate hitting enter when you sendcommands.
  • I assumed you only want to log the "show config running" output
  • use expect eofafter you send "exit"
  • 为简洁起见,我删除了您的所有评论
  • 用于\r模拟在您发出send命令时按 Enter 键。
  • 我假设您只想记录“show config running”输出
  • expect eof发送“退出”后使用

回答by jmrenouard

This is a Perl version for this issue:

这是针对此问题的 Perl 版本:

Install instruction: cpan Expect

安装说明:cpan Expect

This script works perfectely for my needs.

这个脚本非常适合我的需要。

Param 1: connexion string (ex: [email protected]) Param 2: clear text password Param 3: command to execute

参数 1:连接字符串(例如:[email protected]) 参数 2:明文密码 参数 3:要执行的命令

#!/usr/bin/perl
use strict;

use Expect;

my $timeout=1;

my $command="ssh ".$ARGV[0]." ".$ARGV[2];

#print " => $command\n";

my $exp = Expect->spawn($command) or die "Cannot spawn $command: $!\n";
$exp->raw_pty(1);

LOGIN:
$exp->expect($timeout,
        [ 'ogin: $' => sub {
                     $exp->send("luser\n");         
                     exp_continue; }
        ],
    [ 'yes\/no\)\?\s*$' => sub {
              $exp->send("yes\n");
              goto LOGIN;
              }
    ],
        [ 'assword:\s*$' => sub {
                      $exp->send($ARGV[1]."\n");
            #print "password send : ", $ARGV[1];
                      exp_continue; }
        ],
        '-re', qr'[#>:] $'
);
$exp->soft_close();

回答by andrade

A possibility is to pass the IP address as a parameter in your expect script:

一种可能性是在您的期望脚本中将 IP 地址作为参数传递:

set host_ip [lindex $argv 0]

and then make a shell script, calling your expect script inside a while loop:

然后制作一个 shell 脚本,在 while 循环中调用您的期望脚本:

ips_file="list.txt"

while read line
do
    your_expect_script line
done < $ips_file

回答by Gunjan Srivastava

or Use set ip [gets stdin] to ip address from user input.

或使用 set ip [gets stdin] 到用户输入的 ip 地址。

for example-

例如-

puts "Enter your ip address\n" set ip [get stdin]

puts "输入你的 ip 地址\n" set ip [get stdin]

use this in spawn,We can do the same for multiple ip address using loop- spawn ssh $ip -l admin

在 spawn 中使用它,我们可以使用 loop-spawn ssh $ip -l admin 对多个 ip 地址执行相同的操作