Stored procedures 预期脚本:在实际代码之前运行的过程

Stored procedures 预期脚本:在实际代码之前运行的过程,stored-procedures,tcl,expect,procedure,Stored Procedures,Tcl,Expect,Procedure,我正在创建一个expect脚本,以便在管理cisco设备时使用宏 所有连接完成后,我的脚本将等待“#”,这样我就知道用户已准备好输入。如果我在interact之后定义了我的过程,脚本可以正常工作,但显然它还没有被声明,所以脚本失败。如果我在交互之前定义它,我会超时,就像它实际上是“预期的” 为什么这个过程在没有被调用的情况下“运行” proc portSec {port} { send "show port interface $int\r" expect {

我正在创建一个expect脚本,以便在管理cisco设备时使用宏

所有连接完成后,我的脚本将等待“#”,这样我就知道用户已准备好输入。如果我在interact之后定义了我的过程,脚本可以正常工作,但显然它还没有被声明,所以脚本失败。如果我在交互之前定义它,我会超时,就像它实际上是“预期的”

为什么这个过程在没有被调用的情况下“运行”

proc portSec {port} {
        send "show port interface $int\r"
        expect {
                -nocase -re "(invalid)|(ambig}" {
                        puts "\nInvalid Interface\n"
                        return
                }
                -nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
                        set mac $expect_out(1,string)
                }
        }
        ~~~~expect "#" ~~~~~~
        send "show port address \| i $mac\r"
        expect "#"
}

interact {
        "!p" {
                send_user "\nWelcome to macro mode!\nWhich interface would you like to clear port security?: "
                stty echo
                expect_user -re "(.*)\r" {
                        set port $expect_out(1,string)
                }
                stty -echo
                portSec $port
                send "\r"
        }
}
这里是调试

expect: does " \r\nYour password will expire in 1 week, 5 days, 3 hours, 
44 minutes and 56 seconds
\r\r\n\r\nHOSTNAME line 1 \r\n\r\nHOSTNAME#" (spawn_id exp4) 
match glob pattern "#"? yes
expect: set expect_out(0,string) "#"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) " \r\nYour password will expire in 1 week,
5 days, 3 hours, 44 minutes and 56 seconds\r\r\n\r\nHOSTNAME line 1
n\r\nHOSTNAME#"

expect: does "" (spawn_id exp4) match glob pattern "#"? no
expect: timed out
can't read "mac": no such variable
    while executing
"send "show port address \| i $mac\r""
    (file "./ios.exp" line 78)

在调试程序中,我将“~~~~”行平铺在它期望的地方

哦!!!可怜的我。我怎么会错过这个错误!!!:-D

在狠狠地敲了我的头之后,我发现你在expect语句中错误地使用了右大括号

        -nocase -re "(invalid)|(ambig}" {
将其更改为括号可解决此问题。:-)

现在一切都有意义了。但是,为什么
Expect
没有抛出这样的错误呢?那么为什么它必须接受括号的剩余部分作为正确的部分呢

由于右大括号放错了位置,
Expect
假设it关闭第一个Expect语句。剩下的代码段是

    # two code segments enclosed in braces 
    # 'Expect' assumes these two as pattern-action pair
    # which is why no errors thrown for these blocks.
    {
        puts "\nInvalid Interface\n"
        return
    }
    -nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
        set mac $expect_out(1,string)
    }
};# This one closes the proc 'portSec'
####### Below code is now in global scope #########3
expect "#"; # Now, wait for '#'
# Send this command now, but wait...
# I don't know about the variable 'mac'
send "show port address \| i $mac\r"
expect "#"
因此,将错误消息抛出为
无法读取“mac”:没有此类变量

最终产品:

#port security clear feature
proc clearPortSec {} {
        send_user "\n=====\nWelcome to the Port Security Macro!!!!!\nWhich interface would you like to clear port security?: "
        #interact seems to turn of user echoing... turn it back on so the user can make changes
        stty echo
        expect_user -re "(.*)\r" {
                set port $expect_out(1,string)
        }
        stty -echo
        #send ctrl+u to clear the line, and send ctrl+z so we know we are in enable mode
        send "\025\032\r"
        expect "#"
        #verify it is explicitly an access port, if not we don't do the operations to prevent trunks from being shut
        send "sho run int $port \| i switchport mode access\r"
        expect {
                -nocase -re "\r\n\[ \]*switchport mode access\[ \]*\r\n.*#" {
                        send "\rshow port interface $port\r"
                        expect {
                                #grabs offending mac address on this port
                                -nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
                                        set mac $expect_out(1,string)
                                        expect "#"
                                        #finds where switch learned the offending mac
                                        send "show port address \| i $mac\r"
                                        expect {
                                                #case where switch learned mac from another interface
                                                -nocase -re "sticky +(\[^ \]+)" {
                                                        set offendport $expect_out(1,string)
                                                        puts "\n=====\nMac was found on interface $offendport. Clearing $offendport\n====="
                                                        #clear port mac was found on
                                                        expect "#"
                                                        send "\rconf t\r"; expect "#"
                                                        send "interface $offendport\r"; expect "#"
                                                        send "no switchport port-security mac-address sticky\r"; expect "#"
                                                        send "switchport port-security mac-address sticky\r"; expect "#"
                                                        send "shut\r"; expect "#"
                                                        send "no shut\r;" expect "#"
                                                        #switch to original port
                                                        send "interface $port\r"; expect "#"
                                                        send "no switchport port-security mac-address sticky\r"; expect "#"
                                                        send "switchport port-security mac-address sticky\r"; expect "#"
                                                        send "shut\r"; expect "#"
                                                        send "no shut\r"; expect "#"
                                                        #end all operation and print status of each port
                                                        send "end\r"; expect "#"
                                                        send "wr\r"; expect "#"
                                                        puts "\n=====\nSleeping a few seconds..\nPrevious port will NOT be shut. Please shut if necessary\n====="
                                                        send "show int $offendport status\r"; expect "#"
                                                        send "show int $port status\r"; expect "#"
                                                }
                                                #case where switch never learned mac
                                                "#" {
                                                        puts "\n=====\nMac is no where else on the switch, clearing existing sticky mac from $port\n====="
                                                        send "\rconf t\r"; expect "#"
                                                        send "interface $port\r"; expect "#"
                                                        send "no switchport port-security mac-address sticky\r"; expect "#"
                                                        send "switchport port-security mac-address sticky\r"; expect "#"
                                                        send "shut\r"; expect "#"
                                                        send "no shut\r"; expect "#"
                                                        send "end\r"; expect "#"
                                                        send "wr\r"; expect "#"
                                                        puts "\n=====\nSleeping a few seconds..\n====="
                                                        sleep 3
                                                        send "show int $port status\r"
                                                }
                                        }
                                }
                        }
                }
                #if we get back '%' - input error, if we get back '#' switchport mode access doesn't exist
                -re "\[%#\]" {
                        puts "\n=====\nInvalid Interface\nThis script ignores all interfaces that don't have \"Switchport mode access\"\n====="
                        send "\r"
                }
        }
}


# Don't check keys
spawn ssh -o StrictHostKeyChecking=no $username\@$hostname

expect {
        "assword:" {
                interact -o -re "\[#>\]" return {
                        puts "\nLog in Complete"
                }
        }
        timeout {
                puts "=====\n$hostname timeout\n====="
                exit 1
        }
        eof {
                exit 1
        }
}
send "\n"
expect "#"
set timeout -1
interact {
        -re "!\[Hh\]" {
                puts "\n=====\nMacro list\n=====\nPort Security: !p\n\n"
                send "\r"
                expect "#"
        }
        "!p" { clearPortSec }
}

你能把全部代码都贴出来吗?您确定过程
portSec
以前没有调用过吗?这真是令人惊讶。实际上,并不是自动调用proc
portSec
。似乎在某种程度上
expect
认为这些行在进程外部,而不是内部,这就是为什么会发生此问题。这是由于代码
expect{-nocase-re“(无效){124;(ambig}{puts”\n无效接口\n“return}-nocase-re”(\[0-9\]+。\[^\]+。\[^\]+):\[^\]“{set mac$expect\u out(1,字符串)}}
。如果没有这个
expect
,这很好。我想知道并试图找出它为什么会这样。我怀疑方括号
[
。为了匹配文本
[
,应该将它放在
\\\[
。这也解决不了问题。让我试试。哇,我不敢相信这是因为一个简单的打字错误。非常感谢你的帮助!还有额外的解释。在我与
交互之后,再问你一个问题,看起来
expect\u用户
不再回音了……我目前的解决办法是
stty echo
>stty-echo
,但这让用户可以用箭头键做一些有趣的事情。
#port security clear feature
proc clearPortSec {} {
        send_user "\n=====\nWelcome to the Port Security Macro!!!!!\nWhich interface would you like to clear port security?: "
        #interact seems to turn of user echoing... turn it back on so the user can make changes
        stty echo
        expect_user -re "(.*)\r" {
                set port $expect_out(1,string)
        }
        stty -echo
        #send ctrl+u to clear the line, and send ctrl+z so we know we are in enable mode
        send "\025\032\r"
        expect "#"
        #verify it is explicitly an access port, if not we don't do the operations to prevent trunks from being shut
        send "sho run int $port \| i switchport mode access\r"
        expect {
                -nocase -re "\r\n\[ \]*switchport mode access\[ \]*\r\n.*#" {
                        send "\rshow port interface $port\r"
                        expect {
                                #grabs offending mac address on this port
                                -nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
                                        set mac $expect_out(1,string)
                                        expect "#"
                                        #finds where switch learned the offending mac
                                        send "show port address \| i $mac\r"
                                        expect {
                                                #case where switch learned mac from another interface
                                                -nocase -re "sticky +(\[^ \]+)" {
                                                        set offendport $expect_out(1,string)
                                                        puts "\n=====\nMac was found on interface $offendport. Clearing $offendport\n====="
                                                        #clear port mac was found on
                                                        expect "#"
                                                        send "\rconf t\r"; expect "#"
                                                        send "interface $offendport\r"; expect "#"
                                                        send "no switchport port-security mac-address sticky\r"; expect "#"
                                                        send "switchport port-security mac-address sticky\r"; expect "#"
                                                        send "shut\r"; expect "#"
                                                        send "no shut\r;" expect "#"
                                                        #switch to original port
                                                        send "interface $port\r"; expect "#"
                                                        send "no switchport port-security mac-address sticky\r"; expect "#"
                                                        send "switchport port-security mac-address sticky\r"; expect "#"
                                                        send "shut\r"; expect "#"
                                                        send "no shut\r"; expect "#"
                                                        #end all operation and print status of each port
                                                        send "end\r"; expect "#"
                                                        send "wr\r"; expect "#"
                                                        puts "\n=====\nSleeping a few seconds..\nPrevious port will NOT be shut. Please shut if necessary\n====="
                                                        send "show int $offendport status\r"; expect "#"
                                                        send "show int $port status\r"; expect "#"
                                                }
                                                #case where switch never learned mac
                                                "#" {
                                                        puts "\n=====\nMac is no where else on the switch, clearing existing sticky mac from $port\n====="
                                                        send "\rconf t\r"; expect "#"
                                                        send "interface $port\r"; expect "#"
                                                        send "no switchport port-security mac-address sticky\r"; expect "#"
                                                        send "switchport port-security mac-address sticky\r"; expect "#"
                                                        send "shut\r"; expect "#"
                                                        send "no shut\r"; expect "#"
                                                        send "end\r"; expect "#"
                                                        send "wr\r"; expect "#"
                                                        puts "\n=====\nSleeping a few seconds..\n====="
                                                        sleep 3
                                                        send "show int $port status\r"
                                                }
                                        }
                                }
                        }
                }
                #if we get back '%' - input error, if we get back '#' switchport mode access doesn't exist
                -re "\[%#\]" {
                        puts "\n=====\nInvalid Interface\nThis script ignores all interfaces that don't have \"Switchport mode access\"\n====="
                        send "\r"
                }
        }
}


# Don't check keys
spawn ssh -o StrictHostKeyChecking=no $username\@$hostname

expect {
        "assword:" {
                interact -o -re "\[#>\]" return {
                        puts "\nLog in Complete"
                }
        }
        timeout {
                puts "=====\n$hostname timeout\n====="
                exit 1
        }
        eof {
                exit 1
        }
}
send "\n"
expect "#"
set timeout -1
interact {
        -re "!\[Hh\]" {
                puts "\n=====\nMacro list\n=====\nPort Security: !p\n\n"
                send "\r"
                expect "#"
        }
        "!p" { clearPortSec }
}