Мрежовите инженери често се сблъскват със задачата да копират определени фрагменти от бележник в конзолата. Обикновено се налага да копират няколко параметъра: потребителско име/парола и нещо друго. Използването на скриптове ускорява този процес. НО задачата по написването на скрипта и изпълнението му общо трябва да отнемат по-малко време от ръчната настройка, в противен случай скриптовете са безполезни.
За какво е тази статия. Тази статия е част от цикъла Fast Start и е насочена към спестяване на време на мрежовите инженери, при настройка на оборудването (една задача) на няколко устройства. Използва се софтуер SecureCRT и вградената функционалност за изпълнение на скриптове.
Съдържание
Въведение
В програмата SecureCRT от самото начало е внедрен механизъм за изпълнение на скриптове. За какво са нужни скриптовете в терминала:
- Автоматизирано въвеждане и извеждане, и минимална проверка на коректността на входа/изхода.
- Ускоряване на изпълнението на рутинни задачи – намаляване на паузите между настройката на оборудването. (Де факто намаляване на паузите, причинени от времето за изпълнение на действията при copy/paste на едно и също оборудване, при 3 и повече фрагмента от команди за прилагане на оборудването.)
В този документ се разглеждат задачите:
- Създаване на най-простите скриптове.
- Стартиране на скриптове в SecureCRT.
- Примери за използването на прости и усъвършенствани скриптове. (Практика от реалния живот.)
Създаване на най-простите скриптове.
Най-простите скриптове използват само две команди Send и WaitForString. Тази функционалност е достатъчна за 90% (и повече) от изпълняваните задачи.
Скриптовете могат да работят на Python, JS, VBS (Visual Basic), Perl и т.н.
Python
# $language = "Python"
# $interface = "1.0"
def main():
crt.Screen.Synchronous = True
crt.Screen.Send("r")
crt.Screen.WaitForString("name")
crt.Screen.Send("adminr")
crt.Screen.WaitForString("Password:")
crt.Screen.Send("Password")
crt.Screen.Synchronous = False
main()
Файлът с разширение «*.py» обикновено
VBS
# $language = "VBScript"
# $interface = "1.0"
Sub Main
crt.Screen.Synchronous = True
crt.Screen.Send vbcr
crt.Screen.WaitForString "name"
crt.Screen.Send "cisco" & vbcr
crt.Screen.WaitForString "assword"
crt.Screen.Send "cisco" & vbcr
crt.Screen.Synchronous = False
End Sub
Файлът с разширение «*.vbs» обикновено
Създаване на скрипт с помощта на запис на скрипт.
Позволява автоматизиране на процеса на писане на скрипт. Стартирате записа на скрипта. SecureCRT записва командите и последващия отговор на оборудването и ви предоставя готов скрипт.
а. Стартирайте записа на скрипта:
Меню SecureCRT => Script => Start Recording Script
б. Изпълнете действия с конзолата (извършете действия по настройка в CLI).
в. Завършете записа на скрипта:
Меню SecureCRT => Script => Stop Recording Script…
Запазете файла със скрипта.
Пример за изпълнени команди и запазен скрипт:

Стартиране на скриптове в SecureCRT.
След създаването/редактирането на скрипта възниква закономерен въпрос: Как да приложим скрипта?
Съществуват няколко начина:
- Ръчно стартиране от менюто Script
- Автоматично стартиране след свързване (логин скрипт)
- Автоматичен логин без използване на скрипт
- Ръчно стартиране с помощта на бутон в SecureCRT (бутонът все още трябва да се създаде и добави в SecureCRT)
Ръчно стартиране от менюто Script
Меню SecureCRT => Script => Run…
— Последните 10 скрипта се запомнят и са налични за бързо стартиране:
Меню SecureCRT => Script => 1 «Име на файла със скрипта»
Меню SecureCRT => Script => 2 «Име на файла със скрипта»
Меню SecureCRT => Script => 3 «Име на файла със скрипта»
Меню SecureCRT => Script => 4 «Име на файла със скрипта»
Меню SecureCRT => Script => 5 «Име на файла със скрипта»
Автоматично стартиране след свързване (логин скрипт)
Настройките за автоматично вписване на скрипта се конфигурират за запазената сесия: Connection => Logon Actions => Logon script

Автоматичен логин без използване на скрипт
Съществува възможност за автоматично въвеждане на потребителско име и парола без написване на скрипт, като се използва само вграденият функционал на SecureCRT. В настройките на връзката «Connection» => Logon Actions => Automate logon – трябва да се запълнят няколко двойки – които представляват двойки: «Очакван текст» + «Изпращани символи за този текст», такива двойки могат да бъдат много. (Пример: 1-а двойка - очакване за въвеждане на потребителско име, втора - очакване за въвеждане на парола, трета - очакване на покана за привилегирован режим, четвърта - парола за привилегирован режим.)
Пример за автоматично вписване на Cisco ASA:

Ръчно стартиране с помощта на бутон в SecureCRT (бутонът все още трябва да се създаде и добави в SecureCRT)
В SecureCRT можете да зададете скрипт на бутон. Бутонът се добавя на специално създадената за тази цел лента.
а. Добавяме лента в интерфейса: Меню SecureCRT => View => Button Bar
б. Добавяме бутон на лентата и добавяме скрипт. – Щракваме с десния бутон на мишката върху лентата Button Bar и в контекстното меню избираме опцията «New button…».
в. В диалоговия прозорец «Map Button» в полето «Action» избираме действие (функция) «Run Script».
Указваме подпис под бутона. Цвят за иконата на бутона. Завършваме настройките с натискане на Ok.

Бележка:
Панелът с бутони е много полезна функционалност.
1. Има възможност при влизане в определена сесия да се определи кой панел по подразбиране да се отваря за тази вкладка.
2. Има възможност за стандартни действия с оборудването да се зададат предварително зададени действия: показване на show version, show running-config, запазване на конфигурацията.

На тези бутони не е привързан никакъв скрипт. Само ред с действия:

Настройка – за да се отвори необходимият панел с бутони при превключване на сесията, настройките се извършват в настройките на сесията:

За клиента има смисъл да настрои индивидуални скриптове за влизане и преминаване на панела с често срещани команди за доставчика.
![]()
При натискане на бутона Go Cisco – панелът се превключва на Cisco Button Bar.

Примери за използването на прости и усъвършенствани скриптове. (Практика от реалния живот.)
Обикновените скриптове стигат почти за всички случаи. Но веднъж ми се наложи да усложня скрипта – за да ускори работата. Тази сложност – просто изискваше допълнителни данни в диалоговия прозорец от потребителя.
Запитване на данни от потребителя чрез диалогов прозорец
В скрипта ми имаше 2 запитвания за данни. Това са Hostname и 4-ият октет на IP адреса. За да извърша това действие – потърсих как да го направя и намерих на официалния сайт на SecureCRT (vandyke) – функционалността се нарича prompt.
crt.Screen.WaitForString("-Vlanif200]")
hostnamestr = crt.Dialog.Prompt("Въведете hostname:", "hostname", "", False)
ipaddressstr = crt.Dialog.Prompt("Въведете ip адрес:", "ip", "", False)
crt.Screen.Send("ip address 10.10.10.")
crt.Screen.Send(ipaddressstr)
crt.Screen.Send(" 23r")
crt.Screen.Send("quitr")
crt.Screen.Send("sysname ")
crt.Screen.Send(hostnamestr)
crt.Screen.Send("r")
Тази част от скрипта изискваше Hostname и цифрите от последния октет. Тъй като имаше 15 устройства и данните бяха представени в таблица, копирах стойностите от таблицата и ги вмъквах в диалоговите прозорци. След това скриптът работеше самостоятелно.
FTP копиране на мрежово оборудване.
Този скрипт ми стартира команден прозорец (shell) и копираше данни по FTP. След приключване затваряше сесията. Използването на блокнот за това е невъзможно, тъй като копирането отнема много време и данните в буфера на FTP няма да останат толкова дълго:
# $language = "Python"
# $interface = "1.0"
# Connect to a telnet server and automate the initial login sequence.
# Note that synchronous mode is enabled to prevent server output from
# potentially being missed.
def main():
crt.Screen.Synchronous = True
crt.Screen.Send("ftp 192.168.1.1r")
crt.Screen.WaitForString("Name")
crt.Screen.Send("adminr")
crt.Screen.WaitForString("Password:")
crt.Screen.Send("Passwordr")
crt.Screen.WaitForString("ftp")
crt.Screen.Send("binaryr")
crt.Screen.WaitForString("ftp")
crt.Screen.Send("put S5720LI-V200R011SPH016.patr")
crt.Screen.WaitForString("ftp")
crt.Screen.Send("quitr")
crt.Screen.Synchronous = False
main()
Въвеждане на потребителско име/парола с помощта на скрипт
При един клиент директният достъп до мрежовото оборудване беше ограничен. За да се получи достъп до оборудването, първо трябваше да се свържете с Шлюза по подразбиране, а след това от него на свързаното оборудване. За свързването се използваше SSH клиент, вграден в IOS/ПО на оборудването. Съответно потребителското име и паролата се въвеждаха в консолата. С помощта на следния скрипт потребителското име и паролата се въвеждаха автоматично:
# $language = "Python"
# $interface = "1.0"
# Connect to a telnet server and automate the initial login sequence.
# Note that synchronous mode is enabled to prevent server output from
# potentially being missed.
def main():
crt.Screen.Synchronous = True
crt.Screen.Send("snmpadminr")
crt.Screen.WaitForString("assword:")
crt.Screen.Send("Passwordr")
crt.Screen.Synchronous = False
main()
Забележка: Имаше 2 скрипта. Един за администраторския акаунт, втори за акаунта eSIGHT.
Скрипт с възможност за директно добавяне на данни по време на изпълнение на скрипта.
Задачата беше да се добави статичен маршрут на всичкото мрежово оборудване. Но шлюзът за интернет на всяко оборудване беше различен (и той се различаваше от шлюза по подразбиране). Следният скрипт изкарваше таблицата с маршрути, влизаше в режим на конфигуриране и не завършваше командата (IP адрес на шлюза за интернет) – тази част я добавях аз. След като натиснех Enter, скриптът продължаваше изпълнението на командата.
# $language = "Python"
# $interface = "1.0"
# Connect to a telnet server and automate the initial login sequence.
# Note that synchronous mode is enabled to prevent server output from
# potentially being missed.
def main():
crt.Screen.Synchronous = True
crt.Screen.Send("Zdes-mogla-bit-vasha-reklamar")
crt.Screen.WaitForString("#")
crt.Screen.Send("show run | inc ip router")
crt.Screen.WaitForString("#")
crt.Screen.Send("conf tr")
crt.Screen.WaitForString("(config)#")
crt.Screen.Send("ip route 10.10.10.8 255.255.255.252 ")
crt.Screen.WaitForString("(config)#")
crt.Screen.Send("endr")
crt.Screen.WaitForString("#")
crt.Screen.Send("copy run star")
crt.Screen.WaitForString("[startup-config]?")
crt.Screen.Send("r")
crt.Screen.WaitForString("#")
crt.Screen.Send("exitr")
crt.Screen.Synchronous = False
main()
В този скрипт в реда: crt.Screen.Send(«ip route 10.10.10.8 255.255.255.252 „) не е добавен IP адресът на шлюза и липсва символ на нов ред. Скриптът очаква появата на следващия ред с символите «(config)#» Тези символи се появяваха след като аз въведех IP адреса и натиснех enter.
Заключение:
При написването и изпълнението на скрипта трябва непременно да се спазва правилото: Времето за написването на скрипта и изпълнението му никога не трябва да е повече от времето, което би било необходимо за извършването на същата работа ръчно (copy/paste от бележника, написване и отстраняване на грешки в playbook за ansible, написване и отстраняване на грешки в Python скрипт). Т.е. използването на скрипта трябва да спестява време, а не да харчи време за еднократно автоматизиране на процесите (т.е. когато скриптът е уникален и повторенията няма да се случат отново). Но ако скриптът е уникален и автоматизацията с него и написването/отстраняването на грешки отнема по-малко време отколкото изпълнението по друг начин (ansible, команден прозорец), то скриптът е най-доброто решение.
Отстраняване на грешки в скрипта. Скриптът се развива постепенно, отстраняването на грешки се извършва при тестване на първото, второто, третото устройство, и на четвъртото скриптът вероятно ще бъде напълно работещ.
Стартиране на скрипт (с въвеждане на потребителско име и парола) с помощта на мишката обикновено става по-бързо от копирането на потребителското име и паролата от бележника. Но това не е безопасно от гледна точка на сигурността.
Друг (реален) пример за използване на скрипт: Нямате директен достъп до мрежовото оборудване. Но е необходимо да конфигурирате всичкото мрежово оборудване (да го включите в системата за мониторинг, да настроите допълнителни потребителско име/парола/snmpv3потребител/парола). Имате достъп, когато влезете в основния комутатор, от него отваряте SSH на друго оборудване. Защо не може да се използват средства Ansible. — Защото се натъкваме на ограничение на броя на допустимите едновременни сесии на мрежовото оборудване (line vty 0 4, user-interface vty 0 4) (друг въпрос е как в Ansible да интегрирате различно оборудване с едно и също SSH на първото свързване).
Скриптът намалява времето за дългосрочни операции – например копиране на файлове по FTP. След приключване на копирането, скриптът моментално започва да работи. На човека му е необходимо да види края на копирането, после да осъзнае, че е приключило, и след това да въведе съответните команди. Скриптът прави това обективно по-бързо.
Скриптите се прилагат там, където не е възможно да се използват средства за масово доставяне на данни: Конзола. Или когато част от данните за оборудването е уникална: hostname, management ip address. Или когато написването на програма и отстраняването на грешки в нея е по-сложно от дописването на данните, получени от оборудването по време на работа на скрипта. — Пример със скрипт за записване на маршрут, когато на всяко оборудване IP адресът на интернет доставчика е различен. (Колегите ми са писали такива скриптове — когато DMVPN spoke е бил над 300. Необходимо е било да се променят настройките на DMVPN).
Пример от практиката: Задаване на начални настройки на нов комутатор чрез консолните портове:
А. Вкарах консолния кабел в устройството.
Б. Стартирах скрипта.
В. Изчаках изпълнението на скрипта.
Г. Преместих консолния кабел в следващото устройство.
Д. Ако комутаторът не е последен, преминете отново към точка Б.
В заключение относно работата на скрипта:
- на оборудването е зададен начален парол.
- въведен е потребителско име.
- въведен е уникален IP адрес на устройството.
P. S. операцията трябваше да се повтори. Понеже по подразбиране ssh е оказал несъвместим/изключен. (Да, това е моя грешка.)
Използвани източници.
1.
2.
Приложение 1: Примери на скриптове.
Пример на дълъг скрипт с две заявки: Име на хост и IP адрес. Създаден е за предварителна настройка на оборудването през конзолата (9600 бод). Също така и за подготовка за свързване на оборудването към мрежата.
# $language = "Python"
# $interface = "1.0"
# Connect to a telnet server and automate the initial login sequence.
# Note that synchronous mode is enabled to prevent server output from
# potentially being missed.
def main():
crt.Screen.Synchronous = True
crt.Screen.Send("r")
crt.Screen.WaitForString("name")
crt.Screen.Send("adminr")
crt.Screen.WaitForString("Password:")
crt.Screen.Send("Passwordr")
crt.Screen.Send("sysr")
crt.Screen.WaitForString("]")
crt.Screen.Send("interface Vlanif 1r")
crt.Screen.WaitForString("Vlanif1]")
crt.Screen.Send("undo ip addressr")
crt.Screen.Send("shutdownr")
crt.Screen.Send("vlan 100r")
crt.Screen.Send(" description description1r")
crt.Screen.Send(" name description1r")
crt.Screen.Send("vlan 110r")
crt.Screen.Send(" description description2r")
crt.Screen.Send(" name description2r")
crt.Screen.Send("vlan 120r")
crt.Screen.Send(" description description3r")
crt.Screen.Send(" name description3r")
crt.Screen.Send("vlan 130r")
crt.Screen.Send(" description description4r")
crt.Screen.Send(" name description4r")
crt.Screen.Send("vlan 140r")
crt.Screen.Send(" description description5r")
crt.Screen.Send(" name description5r")
crt.Screen.Send("vlan 150r")
crt.Screen.Send(" description description6r")
crt.Screen.Send(" name description6r")
crt.Screen.Send("vlan 160r")
crt.Screen.Send(" description description7r")
crt.Screen.Send(" name description7r")
crt.Screen.Send("vlan 170r")
crt.Screen.Send(" description description8r")
crt.Screen.Send(" name description8r")
crt.Screen.Send("vlan 180r")
crt.Screen.Send(" description description9r")
crt.Screen.Send(" name description9r")
crt.Screen.Send("vlan 200r")
crt.Screen.Send(" description description10r")
crt.Screen.Send(" name description10r")
crt.Screen.Send("vlan 300r")
crt.Screen.Send(" description description11r")
crt.Screen.Send(" name description11r")
crt.Screen.Send("quitr")
crt.Screen.WaitForString("]")
crt.Screen.Send("stp region-configurationr")
crt.Screen.Send("region-name descr")
crt.Screen.Send("active region-configurationr")
crt.Screen.WaitForString("mst-region]")
crt.Screen.Send("quitr")
crt.Screen.Send("stp instance 0 priority 57344r")
crt.Screen.WaitForString("]")
crt.Screen.Send("interface range GigabitEthernet 0/0/1 to GigabitEthernet 0/0/42r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("description Usersr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port link-type hybridr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("voice-vlan 100 enabler")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("voice-vlan legacy enabler")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port hybrid pvid vlan 120r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port hybrid tagged vlan 100r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port hybrid untagged vlan 120r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("stp edged-port enabler")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("trust 8021pr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control broadcast min-rate 1000 max-rate 1500r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control multicast min-rate 1000 max-rate 1500r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control action blockr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control enable trapr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("quitr")
crt.Screen.Send("interface range GigabitEthernet 0/0/43 to GigabitEthernet 0/0/48r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("description Printersr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port link-type accessr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port default vlan 130r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("stp edged-port enabler")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("trust 8021pr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control broadcast min-rate 1000 max-rate 1500r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control multicast min-rate 1000 max-rate 1500r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control action blockr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control enable trapr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("quitr")
crt.Screen.Send("interface range XGigabitEthernet 0/0/1 to XGigabitEthernet 0/0/2r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("description uplinkr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port link-type trunkr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port trunk allow-pass vlan 100 110 120 130 140 150 160 170 180 200r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("port trunk allow-pass vlan 300r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control broadcast min-rate 1000 max-rate 1500r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control multicast min-rate 1000 max-rate 1500r")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control action blockr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("storm-control enable trapr")
crt.Screen.WaitForString("port-group]")
crt.Screen.Send("quitr")
crt.Screen.Send("ntp-service unicast-server 10.10.10.4r")
crt.Screen.Send("ntp-service unicast-server 10.10.10.2r")
crt.Screen.Send("ntp-service unicast-server 10.10.10.134r")
crt.Screen.Send("ip route-static 0.0.0.0 0.0.0.0 10.10.10.254r")
crt.Screen.Send("interface Vlanif 200r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
crt.Screen.Send("r")
crt.Screen.WaitForString("-Vlanif200]")
hostnamestr = crt.Dialog.Prompt("Enter hostname:", "hostname", "", False)
ipaddressstr = crt.Dialog.Prompt("Enter ip address:", "ip", "", False)
crt.Screen.Send("ip address 10.10.10.")
crt.Screen.Send(ipaddressstr)
crt.Screen.Send(" 24r")
crt.Screen.Send("quitr")
crt.Screen.Send("sysname ")
crt.Screen.Send(hostnamestr)
crt.Screen.Send("r")
crt.Screen.WaitForString("]")
crt.Screen.Synchronous = False
main()
Такива скриптове обикновено не са необходими, но количеството на оборудването – 15 бр. Позволи да се ускори настройката. По-нататък настройването на оборудването стана по-бързо с помощта на Command window на SecureCRT.
Настройка на акаунта за ssh.
Друг пример. Настройка също чрез конзолата.
# $language = "Python"
# $interface = "1.0"
# Connect to a telnet server and automate the initial login sequence.
# Note that synchronous mode is enabled to prevent server output from
# potentially being missed.
def main():
crt.Screen.Synchronous = True
crt.Screen.Send("r")
crt.Screen.WaitForString("name")
crt.Screen.Send("adminr")
crt.Screen.WaitForString("Password:")
crt.Screen.Send("Passwordr")
crt.Screen.WaitForString(">")
crt.Screen.Send("sysr")
crt.Screen.Send("stelnet server enabler")
crt.Screen.Send("aaar")
crt.Screen.Send("local-user admin service-type terminal ftp http sshr")
crt.Screen.Send("quitr")
crt.Screen.Send("user-interface vty 0 4r")
crt.Screen.Send("authentication-mode aaar")
crt.Screen.Send("quitr")
crt.Screen.Send("quitr")
crt.Screen.Synchronous = False
main()
За SecureCRT:Платен софтуер: от 99$ (най-ниската цена само за SecureCRT за една година)
Лицензът за софтуера се закупува веднъж, с поддръжка (за актуализации), след което софтуерът се използва с този лиценз неограничено.
Работи на операционни системи Mac OS X и Windows.
Има поддръжка за скриптове (тази статия)
Има
Serial/Telnet/SSH1/SSH2/Shell на операционната система
Източник: habr.com
