Завершение сеансов spawn в expect

Я пытаюсь решить проблему с помощью сценария Expect, который входит в очень большое количество устройств (тысячи). Скрипт составляет около 1500 строк и достаточно вовлечен; его задача-аудит управляемого оборудования в сети с множеством тысяч узлов. В результате он входит в устройства через telnet, запускает команды для проверки работоспособности оборудования, записывает эту информацию в файл, а затем выходит из системы, чтобы перейти к следующему устройству.

здесь я сталкиваюсь с моим проблема; каждый expect в моем скрипте есть тайм-аут и eof, например:

timeout {
    lappend logmsg "$rtrname timed out while <description of expect statement>"
    logmessage
    close
    wait
    set session 0
    continue
}
eof {
    lappend logmsg "$rtrname disconnected while <description of expect statement>"
    logmessage
    set session 0
    continue
}

мой заключительный expect закрывает каждый сеанс spawn вручную:

-re "OK.*#" {
    close
    send_user "Closing session... "
    wait
    set session 0
    send_user "closed.nn"
    continue
}

продолжение возвращает скрипт к циклу while, который инициирует следующий сеанс spawn, предполагая, что session = 0.

установленный сеанс 0 отслеживает, когда сеанс spawn закрывается вручную по таймауту или через EOF перед открытием нового сеанса spawn, и все, кажется, указывает на то, что spawn сеансы закрываются, но после тысячи или около того порожденных сеансов я получаю следующую ошибку:

spawn telnet <IP removed>
too many programs spawned?  could not create pipe: too many open files

теперь я сетевой инженер, а не администратор UNIX или профессиональный программист, так может ли кто-нибудь помочь мне направить меня к моей ошибке? Закрываю ли я сеансы telnet spawn, но неправильно закрываю канал? Я написал второй, тестовый скрипт, который буквально просто подключается к устройствам один за другим и отключается сразу после формирования соединения. Он не входит в систему и не выполняет никаких команд как и мой основной скрипт, и он работает безупречно через тысячи соединений. Этот скрипт приведен ниже:

#!/usr/bin/expect -f

#SPAWN TELNET LIMIT TEST

set ifile [open iad.list]
set rtrname ""
set sessions 0

while {[gets $ifile rtrname] != -1} {
set timeout 2
spawn telnet $rtrname
incr sessions
send_user "Session# $sessionsn"
expect  {
    "Connected" {
                close
                wait
                continue
                }
    timeout     {
                close
                wait
                continue
                }
    eof         {
                continue
                }
}

в моем основном скрипте я регистрирую каждое соединение и почему они могут EOF или timeout (через процесс logmessage, который записывает конкретную причину в файл), и даже когда я не вижу ничего, кроме успешных порожденных соединений и закрытых соединений, я получаю ту же проблему с моим основным скриптом, но не тестовым скриптом.

Я тут читала убийство процесс IDs, но, как я понимаю,закрыть должен быть убит идентификатор процесса текущей сессии spawn и ждать должен останавливать сценарий, пока процесс не будет мертв. Я также попытался использовать простую команду "exit" с устройств, чтобы закрыть соединение telnet, но это не дает никаких лучших результатов.

мне может просто понадобиться предложение о том, как лучше отслеживать Открытие и закрытие моих сессий и гарантировать, что между устройствами, сеансы spawn не остаются открытыми. Любая помощь, которая может быть предложена, будет высоко оценена.

спасибо!

1 ответов


Ошибки?

spawn telnet слишком много программ породил? не могли создать pipe: слишком много открытых файлов

эта ошибка, вероятно, из-за того, что в вашей системе заканчиваются дескрипторы файлов (или, по крайней мере, исчерпывается количество доступных вам).

Я подозреваю, что причина этого-заброшенные сеансы telnet, которые остаются открытыми.

теперь давайте поговорим о том, почему они все еще могут болтаться.


Даже Не, Близко?

Close может фактически не закрыть соединение telnet, особенно если telnet не распознает, что сеанс был закрыт, только ожидайте сеанса с telnet (см.: команда "закрыть"). В этом случае Telnet, скорее всего, сохраняется в ожидании большего ввода со стороны сети и TCP keepalive.

не все приложения распознают close, который представлен как EOF для принимающего приложения. Из-за этого они могут оставаться открытыми даже когда их вход был закрыт.

скажите "Telnet", все кончено.

в этом случае вам нужно будет прервать telnet. Если вы намерены завершить какую-то работу и выйти. Тогда это именно то, что нам нужно делать.

для " telnet "вы можете чисто выйти, выдав "отправить" 35\r" "(который будет" ctrl+] "на клавиатуре, если вам нужно будет ввести его самостоятельно), а затем" выйти", а затем возврат каретки. Это скажет telnet выйти изящно.

ожидание сценария: запустите telnet, выполните команды, закройте telnet Отрывок:

#!/usr/bin/expect
set timeout 1
set ip [lindex $argv 0]
set port [lindex $argv 1]
set username [lindex $argv 2]
set password [lindex $argv 3]
spawn telnet $ip $port
expect “‘^]’.”
send – – “\r”
expect “username:” {
    send – – “$username\r”
    expect “password:”
    send – – “$password\r”
}
expect “$”
send – – “ls\r”
expect “$”
sleep 2
# Send special ^] to telnet so we can tell telnet to quit.
send “35\r”
expect “telnet>”
# Tell Telnet to quit.
send – – “quit\r”
expect eof
# You should also, either call "wait" (block) for process to exit or "wait -nowait" (don't block waiting) for process exit.
wait

Подождите, Для Финиша.

Expect-команда ожидания

без "ждать", ожидать может разорвать связь с процессом преждевременно, это может привести к созданию зомби в некоторых редких случаях. Если приложение не получило наш сигнал раньше (EOF от close), или если процесс не интерпретирует EOF как выход статус тогда он также может продолжать работать, и ваш сценарий не будет мудрее. С wait мы гарантируем, что не забудем о процессе, пока он не очистится и не выйдет.

в противном случае мы не можем закрыть ни один из этих процессов, пока не ожидаем выхода. Это может привести к тому, что у нас закончатся дескрипторы файлов, если ни один из них не закроется для длительного сценария ожидания (или одного, который подключается к множеству серверов). Как только у нас закончатся дескрипторы файлов, ожидайте, и все, что началось, просто умрет, и вы не увидите эти дескрипторы файлов исчерпаны.

тайм-аут?- Все поймал? Почему?

вы также можете рассмотреть возможность использования "тайм-аута" в случае, если сервер не отвечает, когда ожидается, поэтому мы можем выйти рано. Это идеально подходит для сильно отстающих серверов, которые должны вместо этого получить некоторое внимание администратора.

Catch all может помочь вашему скрипту справиться с любыми неожиданными ответами,которые не обязательно мешают нам продолжать. Мы можем просто продолжить обработку, или мы можно выйти пораньше.

Жду Примеры выдержка:

expect {           
    "password:" {
        send "password\r"
    } "yes/no)?" {
        send "yes\r"
        set timeout -1
    } timeout {
        exit
    # Below is our catch all
    } -re . {
        exp_continue
    #
    } eof {
        exit
    }
}