Представим, что вам нужно развернуть «с нуля» десяток однотипных access-коммутаторов Cisco. Типовая конфигурация включает имя хоста и домена, шлюз по-умолчанию, пароли, список пользователей, IP-адреса для SVI, номера VLAN'ов, настройки транков аплинков и т.д. Вводить это каждый раз руками очень долго и непроизводительно. Разумеется, можно создать типовой конфиг и заливать его по (T)FTP, но, во-первых, это потребует хотя бы минимальной настройки из консоли, во-вторых, изменяемые параметры конфигурации всё равно придётся менять. Для решения подобных (а также многих других) задач Cisco IOS содержит мощное средство автоматизации — встроенный интерпретатор языка Tcl (Cisco IOS scripting w/ Tcl).
Tcl (читается «тикль», иногда «текл») — интерпретируемый язык программирования, разработанный в конце 80-х для встраивания в консольные приложения. Спектр возможностей современного Tcl довольно широк: тут и поддержка ООП, и развитые средства regexp, динамические массивы и т.д.
Поддержка этого языка впервые появилась на платформе Cisco IOS 12.2(3)T (в некоторых источниках указывается на 12.3(2), но я не нашел этому подтверждения) и в данный момент имеет несколько вариантов:
Как определить наличие командного интерпретатора зная модель устройства либо версию IOS? Для этого существует Cisco Feature Navigator:
Пункт меню Research Features позволяет выбрать конкретную версию IOS для заданного IOS Train Release или конкретной аппаратной платформы. Пункт меню Research Software позволяет найти все версии IOS с поддержкой Tcl для заданного hardware. Кликаем, фильтруем поле Filter by по названию (Feature name) «Cisco IOS scripting w/ Tcl» (или просто «Tcl»), название фичи добавляем в список, выбираем Train release и получаем список всех версий IOS, содержащих данную фичу:
К сожалению, база CFN неполная и иногда не показывает всю информацию. Так, для платформы CAT2960S навигатор показал наличие Tcl в релизе IOS 15.2E1 и не показал в релизе 15.2E9, хотя по факту интерпретатор Tcl есть и там, и там.
Что же можно сделать в Cisco IOS используя Tcl? Довольно много: просматривать и изменять конфигурацию, создавать интерактивные сценарии, оперировать объектами MIB, сокетами TCP и UDP и даже… написать целый веб-шелл!
В общем виде программа на языке Tcl содержит последовательность команд, разделенных переводом строки или точкой с запятой. Пример, не требующий пояснений:
Некоторые операторы:
Более полный список см. progopedia.ru/language/tcl
Интерпретатор Tcl запускается командой tclsh из priveleged EXEC-режима:
Выполним первый скрипт:
Выход из интерпретатора — команда
Допустимы множественные сеансы интерпретатора Tcl из разных сессий TTY.
Внутренние команды интерпретатора Tcl:
exec — выполняет заданную в кавычках команду из набора IOS CLI priveleged EXEC.
ios-config — выполняет команду из global configuration mode. За ней в отдельных парных кавычках указываются все последующие команды sub-configuration. Например:
эквивалентно серии команд IOS:
Интерпретатор Tcl не дает процессам exec напрямую взаимодействовать с консолью. Поэтому передача данных в процессы exec, запущенные из оболочки Tcl, происходит с помощью команды typeahead:
Сначала в буфере ввода будут сохранены два символа «y», разделенных переводом строки (\n), затем будет запущена exec-команда reload, которая читает из буфера ввода команды отмены или подтверждения перезагрузки и (если нужно) сохранения конфигурации.
Тикль не поддерживает типизацию, это надо помнить, оперируя с переменными:
Вложенный оператор
Пример процедуры в Tcl:
при вводе фигурной скобки интерпретатор не закроет командную строку до ввода парной закрывающей скобки. Процедура хранится в памяти интерпретатора до завершения сессии интерпретатора командой tclquit. Это дает возможность запускать процедуры и обращаться к переменным ранее запущенных скриптов. Помните, что ошибка в скрипте может привести к зацикливанию и блокировке вашего сеанса (V)TTY! Средств аварийного завершения (типа Ctrl+Break) консоль не имеет, единственный способ — новая сессия и сброс «зависшей» сессии командой
Теперь перейдем к решению практической задачи. Перед нами 48-ми портовый Cat2950S «из коробки». Скрипт, приведенный ниже
Примечание 1. В этом скрипте есть небольшая логическая ошибка. Попробуйте её найти.
Примечание 2. Некоторые текстовые редакторы любят помещать в конце файла непечатаемый символ EoF. Его можно увидеть в консоли IOS, выведя содержимое файла командой cat или more. Наткнувшись на EoF, интерпретатор Tcl выдаст ошибку и проигнорирует всю строку. Поэтому я оставил в конце скрипта экранирующий знак комментария.
Возникает вопрос: а как же записать скрипт в память коммутатора с ненастроенным IP работая только через консольный порт? Не набирать же скрипт руками! Неужели каждый раз вручную настраивать Management Interface и пользоваться FTP? Нет, можно проще. Cisco IOS умеет копировать файлы прямо через последовательный порт консоли по протоколу Xmodem и сохранять их на флеш. Для этого вам понадобится эмулятор терминала с поддержкой Xmodem, например, ZOC или Tera Term (а вот популярный бесплатный Putty, увы, не подойдет!). Копирование выполняется командой IOS copy xmodem: flash:filename , после чего нужно выполнить File Transfer в меню эмулятора терминала:
Также это можно сделать находясь в ROMmon (например, если вы «сносите» конфиг коммутатора, не имея пароля на priveleged EXEC). А вот обратное копирование файлов (с флэш-памяти коммутатора на ПК) не поддерживается.
К сожалению, из Tcl нельзя открыть телнет-сессию на удаленный роутер. При попытке
На этом краткий экскурс в возможности языка Tcl на платформе Cisco IOS завершен, изучить вопрос более подробно вы можете в документе «Cisco IOS Scripting with TCL Configuration Guide» доступном на сайте Cisco.
Что такое Tcl
Tcl (читается «тикль», иногда «текл») — интерпретируемый язык программирования, разработанный в конце 80-х для встраивания в консольные приложения. Спектр возможностей современного Tcl довольно широк: тут и поддержка ООП, и развитые средства regexp, динамические массивы и т.д.
Поддержка этого языка впервые появилась на платформе Cisco IOS 12.2(3)T (в некоторых источниках указывается на 12.3(2), но я не нашел этому подтверждения) и в данный момент имеет несколько вариантов:
- Интерпретатор Tcl с интерфейсом командной строки. Встроен в разные версии платформы Cisco IOS, включая IOS XE и XR и доступен для широкой линейки устройств. Позволяет выполнять команды Tcl, запускать готовые скрипты в виде файлов и т.д. Устройства, использующие в качестве операционной системы не IOS а, например, Cat OS или ASA (в одноименном брандмауэре) командной строки интерпретатора не содержат.
- Т.н. «встроенный менеджер событий» или EEM — система отслеживания событий, позволяющая автоматически на них реагировать в режиме реального времени. Например, осуществлять мониторинг удаленного хоста с уведомлением по e-mail. EEM-сценарии (аплеты) пишутся на Tcl, но сам EEM не предоставляет отдельной командной строки Tcl. Пример использования см. тут. EEM доступен на платформе Nexus (NX OS) и ASA с версии 9.2(1) и выше.
- Системы голосового меню IVR (Interactive Voice Responce).
Как определить наличие командного интерпретатора зная модель устройства либо версию IOS? Для этого существует Cisco Feature Navigator:
Пункт меню Research Features позволяет выбрать конкретную версию IOS для заданного IOS Train Release или конкретной аппаратной платформы. Пункт меню Research Software позволяет найти все версии IOS с поддержкой Tcl для заданного hardware. Кликаем, фильтруем поле Filter by по названию (Feature name) «Cisco IOS scripting w/ Tcl» (или просто «Tcl»), название фичи добавляем в список, выбираем Train release и получаем список всех версий IOS, содержащих данную фичу:
К сожалению, база CFN неполная и иногда не показывает всю информацию. Так, для платформы CAT2960S навигатор показал наличие Tcl в релизе IOS 15.2E1 и не показал в релизе 15.2E9, хотя по факту интерпретатор Tcl есть и там, и там.
Что же можно сделать в Cisco IOS используя Tcl? Довольно много: просматривать и изменять конфигурацию, создавать интерактивные сценарии, оперировать объектами MIB, сокетами TCP и UDP и даже… написать целый веб-шелл!
В общем виде программа на языке Tcl содержит последовательность команд, разделенных переводом строки или точкой с запятой. Пример, не требующий пояснений:
puts "Hello, world!"; puts "My first Tcl IOS script!"
Некоторые операторы:
#
комментарий до конца строкиset a 1
приcвоение a=1$a
получение значения переменной{ }
блочный оператор — определяет тело цикла или условия[ ]
оператор подстановки — при выполнении вместо квадратных скобок будет подставлено вычисленное значение содержащегося в них выражения== <= <>
операторы сравненияputs "text"
вывод строки «text» в stdout (т.е., на консоль)puts $a
аналогично для значения переменной a gets stdin
читает значения из консолиset a [gets stdin]
ввод значения из консоли и присвоение его переменной afor {set i 1} {$i < 10} {inrc i} {....}
цикл for proc {argument, ....} {body}
процедураБолее полный список см. progopedia.ru/language/tcl
Интерпретатор Tcl запускается командой tclsh из priveleged EXEC-режима:
sw#Tclsh
sw(tcl)#
Выполним первый скрипт:
Выход из интерпретатора — команда
tclquit
или просто exit. Tcl чувствителен к регистру, поэтому Puts "Hello, world"
вызовет ошибку, а вот регистр команд оболочки IOS неважен. Все вводимые команды сначала обрабатываются интерпретатором Tcl, если введенная команда является исполнимой с т.з. Tcl, она исполняется и результат выводится на устройство TTY. Если команда не может быть выполнена интерпретатором, она передается парсеру команд IOS. Т.о., один скрипт может комбинировать операторы Tcl и команды IOS. Cреда IOS не содержит полноценного текстового редактора, поэтому pre-defined скрипты нужно создавать внешними средствами и уже потом копировать на flash или в память. Так же поддерживается прекомпиляция скрипта в байт-код с последующим запуском. Запуск файла со скриптом на выполнение осуществляется командой tclsh flash:filename
Допустимы множественные сеансы интерпретатора Tcl из разных сессий TTY.
Внутренние команды интерпретатора Tcl:
exec — выполняет заданную в кавычках команду из набора IOS CLI priveleged EXEC.
sw(tcl)#exec "show int fa0"
выдаст:ios-config — выполняет команду из global configuration mode. За ней в отдельных парных кавычках указываются все последующие команды sub-configuration. Например:
sw(tcl)#ios_config "int fa0" "ip address 192.168.0.1 255.255.255.0" "no shut"
эквивалентно серии команд IOS:
sw#conf te
sw(config)#int fa0
sw(conf-int)#ip address 192.168.0.1 255.255.255.0
sw(conf-int)#no shut
Интерпретатор Tcl не дает процессам exec напрямую взаимодействовать с консолью. Поэтому передача данных в процессы exec, запущенные из оболочки Tcl, происходит с помощью команды typeahead:
typeahead "y\ny"
exec "reload"
Сначала в буфере ввода будут сохранены два символа «y», разделенных переводом строки (\n), затем будет запущена exec-команда reload, которая читает из буфера ввода команды отмены или подтверждения перезагрузки и (если нужно) сохранения конфигурации.
Тикль не поддерживает типизацию, это надо помнить, оперируя с переменными:
Вложенный оператор
[expr {..}]
вычислит значение выражения, заданного в фигурных скобках ($a + $b) и выполнит подстановку этого значения вместо квадратных скобок. Пример процедуры в Tcl:
proc ping_net {x} {
for {set n 1} {$n < $x} {incr n} {
exec "ping 192.168.0.$n"
}
}
при вводе фигурной скобки интерпретатор не закроет командную строку до ввода парной закрывающей скобки. Процедура хранится в памяти интерпретатора до завершения сессии интерпретатора командой tclquit. Это дает возможность запускать процедуры и обращаться к переменным ранее запущенных скриптов. Помните, что ошибка в скрипте может привести к зацикливанию и блокировке вашего сеанса (V)TTY! Средств аварийного завершения (типа Ctrl+Break) консоль не имеет, единственный способ — новая сессия и сброс «зависшей» сессии командой
clear line
.Теперь перейдем к решению практической задачи. Перед нами 48-ми портовый Cat2950S «из коробки». Скрипт, приведенный ниже
- запрашивает с консоли порядковый номер свича sw_num
- задает для него hostname вида switch_<sw_num>
- запрашивает и устанавливает пароль на консоль priveleged EXEC
- настраивает в соответствии с введенным номером свича адрес на его интерфейсе управления Fa0 (192.168.0.х) и интерфейсе Vlan1 (10.0.х.254)
- создает port-based DHCP reservation и пул из 48 адресов, в котором за каждым клиентом зарезервирован один IP-адрес, младший октет которого равен порядковому номеру порта, через который это клиент подключен.
puts "Enter Switch number:"
set sw_num [gets stdin]
ios_config "hostname switch_$sw_num"
puts "Enter password (secret):"
set pass [gets stdin]
ios_config "enable secret 0 $pass"
ios_config "line 0 16" "password 0 $pass" "login"
ios_config "int fa0" "ip address 192.168.0.$sw_num 255.255.255.0" "no shut"
ios_config "int vlan1" "ip address 10.0.$sw_num.254 255.0.0.0" "no shut"
ios_config "ip dhcp use subscriber-id client-id"
ios_config "ip dhcp subscriber-id interface-name"
#перебираем в цикле все 48 портов и для каждого задаем опцию subscriber-id
for {set i 1} {$i <= 48} {incr i} {ios_config "int Gi1/0/$i" "ip dhcp server use subscriber-id client-id"}
ios_config "ip dhcp pool POOL1" "network 10.0.0.0 255.0.0.0" "reserved-only" "default-router 10.10.0.254"
# записываем в пул 48 зарезервированных IP-адресов, привязанных к соотв. порту
for {set i 1} {$i <= 48} {incr i} {ios_config "ip dhcp pool POOL1" "address 10.0.$sw_num.$i client-id Gi1/0/$i ascii"}
#
Примечание 1. В этом скрипте есть небольшая логическая ошибка. Попробуйте её найти.
Примечание 2. Некоторые текстовые редакторы любят помещать в конце файла непечатаемый символ EoF. Его можно увидеть в консоли IOS, выведя содержимое файла командой cat или more. Наткнувшись на EoF, интерпретатор Tcl выдаст ошибку и проигнорирует всю строку. Поэтому я оставил в конце скрипта экранирующий знак комментария.
Возникает вопрос: а как же записать скрипт в память коммутатора с ненастроенным IP работая только через консольный порт? Не набирать же скрипт руками! Неужели каждый раз вручную настраивать Management Interface и пользоваться FTP? Нет, можно проще. Cisco IOS умеет копировать файлы прямо через последовательный порт консоли по протоколу Xmodem и сохранять их на флеш. Для этого вам понадобится эмулятор терминала с поддержкой Xmodem, например, ZOC или Tera Term (а вот популярный бесплатный Putty, увы, не подойдет!). Копирование выполняется командой IOS copy xmodem: flash:filename , после чего нужно выполнить File Transfer в меню эмулятора терминала:
Также это можно сделать находясь в ROMmon (например, если вы «сносите» конфиг коммутатора, не имея пароля на priveleged EXEC). А вот обратное копирование файлов (с флэш-памяти коммутатора на ПК) не поддерживается.
К сожалению, из Tcl нельзя открыть телнет-сессию на удаленный роутер. При попытке
sw(tclsh)#exec "telnet host"
сессия просто подвиснет на этапе ввода пароля. На этом краткий экскурс в возможности языка Tcl на платформе Cisco IOS завершен, изучить вопрос более подробно вы можете в документе «Cisco IOS Scripting with TCL Configuration Guide» доступном на сайте Cisco.
Rulexec
TCL интересный язык. В лиспе всё это списки, в TCL — всё это строки (даже числа).
Весь синтаксис — выполнение процедуры (где первой строкой её имя, остальными — аргументы), двойные кавычки, формирующие строку с пробелами и позволяющие делать ${подстановку_переменных} и [подстановку вызова процедуры], фигурные кавычки, которые возвращают строку как есть.
В итоге, когда мы видим
if {$x == 5} { ... } else { ... }
это на самом деле вызов встроенной процедурыif
, где первый аргумент подаётся в процедуруexpr
, которая умеет брать строки и проверять её на логические условия. А блоки кода — это строки, одна из которых будет за'eval'ена, если условие выполнится.