【问题标题】:show cdp neighbor in expect script在期望脚本中显示 cdp 邻居
【发布时间】:2012-11-14 17:18:00
【问题描述】:

总的来说,我对脚本编写很陌生。我正在编写一个将 ssh 连接到 Cisco 交换机的期望脚本,并运行“show cdp neighbors”命令来获取连接到交换机的所有设备的列表。然后我将输出保存到一个变量中并退出 ssh 会话。 我在包含的文件中设置了用户名和密码。

#!/usr/bin/expect -f
#exp_internal 1

source accountfile
set timeout 10
spawn $env(SHELL)
expect "#"
send "ssh $USERNAME@<hostname>\r"
expect {
  "continue connecting" {
    send_user "Adding host to ssh known hosts list...\n"
    send "yes\n"
    exp_continue
  }
  "Do you want to change the host key on disk" {
    send_user "Changing host key on disk...\n"
    send "yes\n"
    exp_continue
  }
  "assword:" {
    send "$PASSWORD\r"
  }
}
expect "#"
send "term len 0\r"
expect "#"
send "show cdp neighbors\r"
expect "#"
set result $expect_out(buffer)
send "exit\r"
expect "#"

然后我想获取 $result 并查找包含“ R ”的行,并将这些行保存到文件中(R 两边有空格表示路由器,这是我感兴趣的)

问题在于,如果连接设备的名称很长,它会将设备名称放在一行,然后将有关该设备的其余数据放在下一行。所以如果我匹配 'R' 字符串,我不会得到设备的名称,因为名称在前一行。

Device ID        Local Intrfce     Holdtme     Capability Platform  Port ID
...
<device_name_really_long>
                 Gig 2/0/52        171             R S I  WS-C6509  Gig 3/14
<device_name2>   Gig 2/0/1         131             H P M  IP Phone  Port 1
...

有什么想法吗?可能有一个正则表达式可以做到这一点,但我对正则表达式一无所知。

已解决:感谢格伦·杰克曼

我最终不得不添加一个期望条件来检查我是否有一个完整的缓冲区,所以我的最终代码如下所示:

#!/usr/bin/expect
#exp_internal 1
match_max 10000
set expect_out(buffer) {}
set timeout 30

source accountfile
spawn $env(SHELL)
expect "#"
send "ssh $USERNAME@ol2110-3750stack.sw.network.local\r"
expect {
    "continue connecting" {
        send_user "Adding host to ssh known hosts list...\n"
        send "yes\n"
        exp_continue
    }
    "Do you want to change the host key on disk" {
        send_user "Changing host key on disk...\n"
        send "yes\n"
        exp_continue
    }
    "assword:" {
        send "$PASSWORD\r"
    }
}
expect "#"
send "term len 0\r"
expect "#"
send "show cdp neighbors\r"
set result ""
expect {
    {full_buffer} {
        puts "====== FULL BUFFER ======"
        append result $expect_out(buffer)
        exp_continue
    }
    "#" {
        append result $expect_out(buffer)
    }
}
send "exit\r"
expect "#"
set devices [list]
set current_device ""
set lines [split $result "\n"]
foreach line $lines {
    set line [string trim $line]
    if {[llength $line] == 1} {
        set current_device $line
        continue
    }
    set line "$current_device$line\n"
    if {[string match {* R *} $line]} {
        lappend devices $line
    }
    set current_device ""
}

puts $devices

【问题讨论】:

    标签: regex expect cisco


    【解决方案1】:
    set devices [list]
    set current_device ""
    foreach line [split $result \n] {
        if {[llength [split [string trim $line]]] == 1} {
            set current_device $line
            continue
        }
        set line "$current_device$line"
        if {[string match {* R *} $line]} {
            lappend devices $line
        }
        set current_device ""
    }
    
    # devices list should now contain "joined" routers.
    

    【讨论】:

    • 当我这样做然后放入 $devices 时,这就是我得到的:
    • } 演出 2/0/52 174 R S I WS-C6509 演出 3/14
    • 换句话说,我只得到一行(我应该有大约 8 行),这只是第二行,前面有一个右括号。这会让人觉得某处有一个不匹配的括号,但我没有看到...
    • 设备名有空格吗?
    • OK,用 \r 代替 \n 分割行,并在第一个 if 语句的第一行和 set line "$current 之前添加 "set line [string trim $line]" ...”似乎可以解决问题(有点)。我现在有一个列表,其中包含已“加入”的“未加入”路由器,但只有那些路由器。开始时都在一条线上的路由器不会放在列表中。
    猜你喜欢
    • 2023-03-05
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    相关资源
    最近更新 更多