用于Cisco / Juniper配置备份的EXPECT脚本

时间:2015-01-12 06:14:53

标签: configuration scripting expect cisco

首先我要问这是脚本编程的初学者,目前我有一个期望脚本自动登录到预定义的思科设备并运行某些命令,我​​想更新我的脚本,以便这个相同的脚本也可以备份瞻博网络设备

理想情况下,我希望脚本执行的操作是(伪代码)

      login / send credentials
      expect prompt
      send command "show version"
      if output contains "JUNOS" then
                send command 1
                send command 2
                send command 3
      otherwise if output contains "Cisco" then
                send command 1
                send command 2
                send command 3

我很抱歉,如果以前曾经问过这个问题,但是我尝试过搜索和搜索,如果有人能帮忙解决这个问题我找不到答案,我会非常感激。我还包含了我当前的期望脚本供您参考(此脚本由BASH脚本调用)

set timeout 5
set hostname [lindex $argv 0]
set username "user"
set password "pass"

spawn ssh $username@$hostname

expect "Password:"
send "$password\n"
expect "#" {
send "terminal length 0\n"
send "show running-config\n"
expect "end\r"
send "\n"
send "exit\n"
}

----更新---

感谢您输入Dinesh - 我已更新我的脚本以包含您提供的内容(如下所示)

set timeout 5
set hostname [lindex $argv 0]
set username "user"
set password "pass"
set prompt "(>|#|\\\$) $"

spawn ssh $username@$hostname


expect "*assword:"
send $password\r
send \r
expect -re $prompt {

    send "show version\r"
    expect -re $prompt
    expect *;

    set output $expect_out(buffer);

    #Basic string check logic with Tcl
    if { [string first "JUNOS" $output ]!=-1 } {
        send "show configuration | display set | no-more"
    expect -re $prompt
    send "exit\r"
    } else {
    send "terminal length 0\r"
    expect -re $prompt
    send "show run\r"
    expect "end"
    send \r
    expect -re $prompt
    send "exit\r"
    }
}

然而,当我运行此脚本时,我遇到的问题是“show version”的输出似乎与我的“字符串检查”不匹配,因此脚本忽略“if”语句并继续执行“ “声明。

“show version”命令的输出如下 - 我需要修改什么才能使“JUNOS”字符串匹配?

user@host> show version
Hostname: host
Model: srx240h
JUNOS Software Release [11.4R7.5]

---编辑2:脚本输出

05c4rw@testpc:~/script$ ./ssh.sh
spawn ssh user@juniperhost
## LOGIN BANNER - Removed for brevity

user@juniperhost's password:
--- JUNOS 11.4R7.5 built 2013-03-01 11:40:03 UTC
user@juniperhost> show version
Hostname: juniperhost
Model: srx240h
JUNOS Software Release [11.4R7.5]

user@juniperhost> show configuration | display set | no-more
set version 11.4R7.5

## *** OUTPUT REMOVED FOR BREVITY / PRIVACY ***

## *** END OF OUTPUT from previous command

 user@juniper> spawn ssh user@ciscohost
 password:
 ## LOGIN BANNER - removed for brevitiy

 ciscohost#05c4rw@testpc:~/script$

2 个答案:

答案 0 :(得分:1)

set timeout 5
set hostname [lindex $argv 0]
set username "user"
set password "pass"

spawn ssh $username@$hostname


expect "Password:"
send "$password\r"
expect "#" {

    send "terminal length 0\r"
    expect "#"
    # This is to clean up the previous expect_out(buffer) content
    # So that, we can get the exact output what we need.
    expect *;         
    send "show running-config\r"
    expect "end"

    #Now, the content of 'expect_out(buffer)' has the whole 'show run' output
    set output $expect_out(buffer);

    #Basic string check logic with Tcl  
    if { [string first "JUNOS" $output ]!=-1 } {
           # Apply your logic here
           # send "command1"
           # expect "#"
    } else {
           # Same as above        

           # I assume, there are 2 possibilities. So, keeping 'else' part alone.
           # Have 'else if', if you have more than 2.

    }
}

请注意,脚本发送的每一行都以\r终止。这表示返回字符,如果您在shell中输入这些行,则正是您要按的那样,这正是Expect必须发送的内容。将命令终止发送到\n后跟的进程是一个常见的错误。在此上下文中,\n表示换行符。您没有使用换行符交互式结束行。所以Expect也不能。因此,请始终使用\r

如果您有兴趣了解有关您需要expect *的原因的更多信息,可以查看here。 (这是一个单独的故事)

我可以看到,在您的示例中,有一些命令仅用于send。基本上,expect将使用两个可行的命令,例如sendexpect。在这种情况下,如果使用send,则必须在之后拥有expect(在大多数情况下)。 (反之亦然,不要求是强制性的)

这是因为如果不这样做,我们将错过生成过程中发生的事情,因为expect将假设您只需要发送一个字符串值而不期望会话中的任何其他内容。

答案 1 :(得分:0)

这可能不是你想要的,但我想我会发布以防万一。

您可能希望查看类似Rancid的内容,而不是使用这些脚本。 Rancid不仅会备份您的设备配置,它还会在预定义的时间间隔内为您提供设备上的差异(例如,如果您将间隔设置为15分钟,则每隔15分钟就会登录到您的设备配置,备份它们并使用以前的版本进行差异并显示差异