2012-02-16 50 views
0

我已经编写了一个小型的Expect脚本来登录到思科设备;一旦登录,我想反复运行命令并输出grepMixing Expect和BASH

#!/usr/bin/expect 

send_user "Device name: " 
expect_user -re "(.*)\n" 
set host $expect_out(1,string) 

send_user "Username: " 
expect_user -re "(.*)\n" 
set user $expect_out(1,string) 

stty -echo 
send_user -- "Password: " 
expect_user -re "(.*)\n" 
set pass $expect_out(1,string) 
stty echo 

send_user "show int " 
expect_user -re "(.*)\n" 
set intf $expect_out(1,string) 
send_user "\n" 

spawn telnet $host 
expect "Username:" 
send "$user\r" 
expect "Password:" 
send "$pass\r" 
expect ">" 

此时我们已经登录到设备,我想重复执行命令“show int xxx”,并为特定行输出grep。 grep不在预期中,也不是像sleep这样的命令,所以我可以循环执行我的特定行中的show int命令,grepping。我如何将Expect和Bash混合在一起?

UPDATE:我现在已经完成了这个脚本,一旦我完成了这个最后的障碍,我会发布完整的脚本。一行set bytesnow [exec grep "packets input" \< showint | cut -d \ -f 9]正在抛出错误;

child process exited abnormally 
    while executing 
"exec grep "packets input" < \showint | cut -d \ -f 9" 

但它在我写的测试脚本中正常工作。文件./showint在那里,在命令行上运行该命令工作正常?我无法弄清楚什么是错的?

UPDATE:更多的调查(http://wiki.tcl.tk/8489)已经表明我,grep退出时的状态码1,这意味着没有模式匹配被发现了,把命令从工作就好命令行?即使使用/ full/path/to/showint。

END:我解决了我的错误,意识到我过去的傻子,下面回答。感谢所有您的帮助:d

+0

哈!错误,纠正,欢呼;) – jwbensley 2012-02-16 23:42:49

+0

好吧,它看起来像你正在寻找字段9在'路由器#sh int |我将数据包输入字段用空格作为分隔符。我只在输出中看到8个字段。你能告诉我们你想完成什么吗? '798518177数据包输入,60933723489字节,0无缓冲区' – resmon6 2012-02-17 00:24:52

+0

我使用了“-f 9”,因为交换机/路由器上的输出线在开始处有几个空格来缩进该行。我正在尝试按照该行输出的字节值工作。在底部查看我的答案。谢谢:) – jwbensley 2012-02-17 01:02:56

回答

0

这是我的第一个Expect脚本,它的目的是给出一个接口的实时(几乎1秒!)吞吐量。下面的例子给出了接口输入速度,因为我们grep为包含“数据包输入”的行。将其更改为“数据包输出”以获取该接口的实时输出速率。

#!/usr/bin/expect 

# Long delay for those tricky hostnames 

set timeout 60 

# Prompt user for device name/IP, username, password, 
# and interface to query (gi0/2) 

send_user "Device name: " 
expect_user -re "(.*)\n" 
set host $expect_out(1,string) 

send_user "Username: " 
expect_user -re "(.*)\n" 
set user $expect_out(1,string) 

stty -echo 
send_user "Password: " 
expect_user -re "(.*)\n" 
set pass $expect_out(1,string) 
send_user "\n" 
stty echo 

send_user "show int " 
expect_user -re "(.*)\n" 
set intf $expect_out(1,string) 
send_user "\n" 

spawn telnet $host 
expect "Username:" 
send "$user\r" 
expect "Password:" 
send "$pass\r" 
expect ">" 

set byteslast 0 
set bytesnow 0 

log_user 0 

# Enter a continuous loop grabbing the number of bytes that 
# have passed through an interface, each second. 
# The different in this number each cycle, is essentially 
# how much traffic this interface is pushing. 

while { true } { 
    send "show int $intf\r" 
    expect ">" 

    set showint [open "showint" "w"] 
    puts $showint $expect_out(buffer) 
    close $showint 

    set bytesnow [exec grep "packets input" \< showint | cut -d \ -f 9] 

    if { $bytesnow > $byteslast } { 
    set diff [expr $bytesnow - $byteslast] 
    set bps [exec expr "$diff" \* 8] 
    set kbps [exec expr "$bps" \/ 1000] 
    } elseif { $bytesnow < $byteslast } { 
    set diff [expr $byteslast - $bytesnow] 
    set bps [exec expr "$diff" \* 8] 
    set kbps [exec expr "$bps" \/ 1000] 
    } elseif { $bytesnow == $byteslast } { 
    set kbps 0 
    } 

    set byteslast $bytesnow 
    puts "$kbps Kbps\r" 

    sleep 1 
} 

因为这是我的第一个Expect脚本,我毫不怀疑它可以更有效和更明确的书面(总是这样,我觉得),因此,如果任何人有这个任何指针我所有的耳朵! :)

我的exec grep命令的问题竟然是在那之前,我打开“showint”的文件,我没有关闭,并且我试图访问另一个文件;学校男孩错误!

+1

如果您希望保持一切,您可以使用TCL命令[regexp](http://www.tcl.tk/man/tcl8.4/TclCmd/regexp.htm)你的grep。我相信你的命令是'[regexp {\(\ d + \)bytes} $ showint bytesnow]'。另外,当你使用内置的TCL'expr'命令时,你的'exec expr'行不必要地调用shell命令'expr'。只需在这些命令中删除'exec'即可。 – resmon6 2012-02-17 04:13:47

+0

另外,更优雅的长期解决方案是使用snmp。你有没有签出[MRTG](http://oss.oetiker.ch/mrtg/)或[NMIS](http://www.sins.com.au/nmis/)? – resmon6 2012-02-17 14:52:48

+0

我有SNMP的全面监控,但我需要此脚本进行故障排除,当我想现在看到接口流量,而不是在五分钟内轮询器运行:) – jwbensley 2012-02-17 16:16:31

1

这是我会做什么

log_user 0 
while(1) { 
    send -- "sh int $intf | i packets input\r" 
    set timeout 5 
    expect { 
    -re "^ +(\d+) packets" { send_user -- "$expect_out(1,string)" } 
    timeout { send_user "broke?\n" } 
    } 
} 

这会让你输入数据包的数量。

+0

虽然这是一个非常酷的想法,我非常喜欢,但我的脚本的目的(我没有解释过,所以这是我的错)是获得当前接口的吞吐量。请参阅下面的答案以获得完整的脚本。感谢您的好主意,但:D – jwbensley 2012-02-17 00:53:20