Сценарий EXPECT для резервного копирования конфигурации Cisco / Juniper

Во-первых, я спрашиваю об этом как новичок в написании сценариев, в настоящее время у меня есть ожидаемый сценарий, который автоматически входит в систему на предопределенных устройствах Cisco и выполняет определенные команды, я хотел бы обновить свой сценарий, чтобы этот же сценарий мог также создавать резервные копии устройств Juniper.

В идеале я хотел бы, чтобы скрипт делал (в псевдокоде)

      login / send credentials
      expect prompt
      send command "show version"
      if output contains "JUNOS" then
                send command 1
                send command 2
                send command 3
      otherwise if output contains "Cisco" then
                send command 1
                send command 2
                send command 3

Извините, если об этом спрашивали раньше, но я пытался искать и искать и не смог найти ответ, если кто-нибудь может помочь с этим, я был бы очень признателен. Я также включил свой текущий сценарий ожидания для вашей справки (этот сценарий вызывается сценарием BASH)

set timeout 5
set hostname [lindex $argv 0]
set username "user"
set password "pass"

spawn ssh $username@$hostname

expect "Password:"
send "$password\n"
expect "#" {
send "terminal length 0\n"
send "show running-config\n"
expect "end\r"
send "\n"
send "exit\n"
}

---- ОБНОВИТЬ ---

Спасибо за ваш вклад, Динеш - я обновил свой сценарий, чтобы включить то, что вы предоставили (как показано ниже)

set timeout 5
set hostname [lindex $argv 0]
set username "user"
set password "pass"
set prompt "(>|#|\\\$) $"

spawn ssh $username@$hostname


expect "*assword:"
send $password\r
send \r
expect -re $prompt {

    send "show version\r"
    expect -re $prompt
    expect *;

    set output $expect_out(buffer);

    #Basic string check logic with Tcl
    if { [string first "JUNOS" $output ]!=-1 } {
        send "show configuration | display set | no-more"
    expect -re $prompt
    send "exit\r"
    } else {
    send "terminal length 0\r"
    expect -re $prompt
    send "show run\r"
    expect "end"
    send \r
    expect -re $prompt
    send "exit\r"
    }
}

Однако, когда я запускаю этот скрипт, проблема заключается в том, что вывод «show version», похоже, не соответствует моей «проверке строки», и поэтому скрипт игнорирует оператор «if» и переходит к оператору «else». .

Вывод команды "show version" приведен ниже - что мне нужно изменить, чтобы строка "JUNOS" совпадала?

user@host> show version
Hostname: host
Model: srx240h
JUNOS Software Release [11.4R7.5]

--- РЕДАКТИРОВАТЬ 2: вывод из скрипта

05c4rw@testpc:~/script$ ./ssh.sh
spawn ssh user@juniperhost
## LOGIN BANNER - Removed for brevity

user@juniperhost's password:
--- JUNOS 11.4R7.5 built 2013-03-01 11:40:03 UTC
user@juniperhost> show version
Hostname: juniperhost
Model: srx240h
JUNOS Software Release [11.4R7.5]

user@juniperhost> show configuration | display set | no-more
set version 11.4R7.5

## *** OUTPUT REMOVED FOR BREVITY / PRIVACY ***

## *** END OF OUTPUT from previous command

 user@juniper> spawn ssh user@ciscohost
 password:
 ## LOGIN BANNER - removed for brevitiy

 ciscohost#05c4rw@testpc:~/script$

person 05c4rw    schedule 12.01.2015    source источник
comment
Поместите код expect * перед отправкой show version и напечатайте значение output. Обновите так же здесь.   -  person Dinesh    schedule 13.01.2015
comment
Привет, Динеш, спасибо за то, что я обновил конфигурацию, и теперь он успешно выполняет оператор if, однако оператор else не работает - в качестве теста у меня есть два устройства в списке, которые он автоматически регистрирует в Juniper. сначала и Cisco после этого - после успешного завершения части Juniper (если) он входит в устройство Cisco и сидит в подсказке перед выходом (не выдавая никаких команд)   -  person 05c4rw    schedule 13.01.2015
comment
В этом случае напечатайте значение вывода (просто для нашего удобства) и проверьте, что оно содержит, прежде чем переходить к циклу if-else.   -  person Dinesh    schedule 13.01.2015
comment
Я поместил вывод в основной вопрос из-за проблем с форматированием, спасибо.   -  person 05c4rw    schedule 13.01.2015
comment
Я имел в виду напечатать значение переменной output. Код не может пропустить цикл if-else. Поток кода должен быть либо с if, либо с else   -  person Dinesh    schedule 13.01.2015


Ответы (2)


set timeout 5
set hostname [lindex $argv 0]
set username "user"
set password "pass"

spawn ssh $username@$hostname


expect "Password:"
send "$password\r"
expect "#" {

    send "terminal length 0\r"
    expect "#"
    # This is to clean up the previous expect_out(buffer) content
    # So that, we can get the exact output what we need.
    expect *;         
    send "show running-config\r"
    expect "end"

    #Now, the content of 'expect_out(buffer)' has the whole 'show run' output
    set output $expect_out(buffer);

    #Basic string check logic with Tcl  
    if { [string first "JUNOS" $output ]!=-1 } {
           # Apply your logic here
           # send "command1"
           # expect "#"
    } else {
           # Same as above        

           # I assume, there are 2 possibilities. So, keeping 'else' part alone.
           # Have 'else if', if you have more than 2.

    }
}

Обратите внимание, что каждая строка, отправляемая сценарием, заканчивается \r. Это символ возврата, и это именно то, что вы бы нажали, если бы ввели эти строки в оболочке, так что это именно то, что Expect должен отправить. Распространенной ошибкой является завершение отправки команд процессу, за которым следует \n. В этом контексте \n обозначает символ перевода строки. Вы не завершаете строки интерактивным переводом строки. Так что Expect тоже не должно. Поэтому всегда используйте \r.

Вы можете взглянуть на здесь, если вам интересно узнать больше о том, зачем вам expect *. (это отдельная история)

Я вижу, что в вашем примере есть некоторые команды, используемые только с send. По сути, expect будет работать с двумя возможными командами, такими как send и expect. В этом случае, если используется send, то после обязательно иметь expect (в большинстве случаев). (в то время как наоборот не обязательно)

Это потому, что без этого мы упустим то, что происходит в порожденном процессе, поскольку expect будет считать, что вам просто нужно отправить одно строковое значение и не ожидать ничего другого от сеанса.

person Dinesh    schedule 12.01.2015
comment
Спасибо Динеш за ваш подробный ответ, я обновил свой первоначальный вопрос результатами из-за ограничений на количество символов, установленных для ответов здесь. - person 05c4rw; 13.01.2015

Возможно, это не то, что вы искали, но я решил опубликовать это на всякий случай.

Возможно, вы захотите изучить что-то вроде Rancid вместо этих сценариев. Rancid не только сделает резервную копию конфигураций вашего устройства, но также предоставит вам diff на устройствах, которыми он управляет, через заранее определенные интервалы (например, если вы установите интервал на 15 минут, rancid будет входить на ваши устройства каждые 15 минут). конфиги, сделайте их резервную копию и сравните с предыдущей версией и покажите вам diff)

person RedDevil    schedule 09.02.2016
comment
@thanksd rancid — это скорее инструмент, чем фрагмент кода. Вы можете получить более подробную информацию здесь shrubbery.net/rancid - person RedDevil; 12.06.2016