Смешивание Expect и BASH

Я написал небольшой сценарий Expect для входа в устройство Cisco; после входа в систему я хочу повторно запустить команду и grep вывод.

#!/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 нет ни в Expect, ни в такой команде, как sleep, поэтому я могу зациклиться на выполнении команды show int, grepping из моей конкретной строки. Как я могу так смешивать Expect и Bash?

ОБНОВЛЕНИЕ: я почти закончил сценарий, я опубликую полный сценарий, как только преодолею это последнее препятствие. Строка 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 есть, запуск этой команды в командной строке работает нормально? Я не могу понять, что не так?

ОБНОВЛЕНИЕ: Дальнейшее расследование (http://wiki.tcl.tk/8489) показало мне, что grep завершает работу с кодом состояния 1, что означает, что совпадений с шаблоном не найдено, команда put работает нормально из командной строки? Даже с /full/path/to/showint.

КОНЕЦ: я исправил свою ошибку, поняв, каким дураком я был, ответил ниже. Всем спасибо за помощь :D


person jwbensley    schedule 16.02.2012    source источник
comment
Ха! Опечатка, исправил, ура ;)   -  person jwbensley    schedule 17.02.2012
comment
Похоже, вы ищете поле 9 в поле router#sh int <int> | i packets input с пробелом в качестве разделителя. Я вижу только 8 полей в моем выводе. Можете ли вы рассказать нам, чего вы пытаетесь достичь? 798518177 packets input, 60933723489 bytes, 0 no buffer   -  person resmon6    schedule 17.02.2012
comment
Я использовал -f 9, потому что эта строка вывода на коммутаторе/маршрутизаторе имеет несколько пробелов в начале для отступа строки. Я пытаюсь проложить себе путь к значению байтов этой строки вывода. Смотрите мой ответ внизу. Спасибо :)   -  person jwbensley    schedule 17.02.2012


Ответы (2)


Это то, что я бы сделал

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" }
  }
}

Это даст вам количество входных пакетов.

person resmon6    schedule 17.02.2012
comment
Хотя это действительно крутая идея, которая мне очень нравится, цель моего скрипта (которую я не объяснил ранее, так что это моя вина) — получить текущую пропускную способность интерфейса. Полный сценарий смотрите в моем ответе ниже. Но спасибо за отличную идею :D - person jwbensley; 17.02.2012

Это мой первый 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", я не закрыл, и я пытался получить доступ к другому файлу; ошибка школьника!

person jwbensley    schedule 17.02.2012
comment
Если вы хотите, чтобы все было ожидаемо, вы можете использовать команду TCL regexp для вашего grep. Я полагаю, что ваша команда будет [regexp { \(\d+\) bytes} $showint bytesnow]. Кроме того, ваши строки [exec expr без необходимости вызывают команду оболочки expr, когда вы можете использовать встроенную команду TCL expr. Просто избавьтесь от exec в этих командах. - person resmon6; 17.02.2012
comment
Кроме того, более элегантным долгосрочным решением является использование snmp. Проверяли ли вы MRTG или NMIS? - person resmon6; 17.02.2012
comment
У меня есть SNMP для общего мониторинга, но этот скрипт мне понадобился для устранения неполадок, когда я хочу видеть трафик интерфейса прямо сейчас, а не через пять минут, когда запустится поллер :) - person jwbensley; 17.02.2012