Ideea de la care am pornit a fost sa fac un script in BASH si cu ajutorul limbajul EXPECT sa execut comenzi, unele interactive (adica trebuie sa introduci parametrii, de ex. comanda enable
solicita introducerea unui parole s.a.m.d), pe un numar de elemente de retea (aici Cisco) a.i. sa pot configura la orice moment un numar cat mai mare din acestea fara sa ma conectez eu pe fiecare in parte.
Ziceam pe cand predam cursuri - si in continuare cred in faptul - ca si lenea a dus la progres.
Ceea ce am scris mai jos nu necesita cunostinte avansate de BASH scripting si de EXPECT, eu nu stiu mai mult de genunchiul broastei; totusi in 3-4 zile am reusit sa inteleg sintaxa de baza pt BASH si EXPECT si iata ce a iesit.
Scriptul se lanseaza cu comanda sh <numescript>.sh <inputFile>.csv
Fisierul cu datele de intrare <inputFile>.csv este in format csv, fiecare linie este de forma:
ipaddr,<numefisier>.txt (de ex: 192.168.1.2,routerBackbone.txt)
<numefisier>.txt contine pe fiecare linie comenzile pe care doriti sa le executati pe fiecare element de retea identificat cu ipaddr, de ex.:
show clock
conf t
interface Gi 0/0/0
no shutdown
ip address 10.0.0.0.1 255.255.255.0
exit
exit
write memory
De la linia de comanda se introduce user/parola, parola VTY si enable secret; doar userul este afisat pe ecran
Erorile se salveaza in fisierul <numefisier>.error.log, iar outputul comenzilor executate pe fiecare element de retea se savleaza in fisierul <numefisier>.report
Va rog sa inlocuiti <numefisier> cu ceva care are sens pt fiecare.
Continutul fisierului <numescript>.sh este:
#!/bin/bash
#functia de mai jos se apeleaza cu 3 parametrii si practic trimite 5 mesaje ICMP echo de marime 512 octeti
#si asteapta raspuns timp de 10 sec
#nu ma intereseaza sa capturez outputul comenzii ping si nici eventualele erori
isAlive() {
host=$1
contor=$2
rows=$3
echo -e "\n$contor/$rows#####start probing...$host"
ping -c 5 -s 512 -w 10 $host > /dev/null 2>&1
}
#IFS este parametrul prin care ii transmit BASH ca Internal Field Separator este ,
IFS=","
#mai jos ii transmit BASH ca fisierul de intrare este primul argument din comanda de lansare
inputFile=$1
#ma asigur ca fisierul de intrare exista (-f) si ca are o lungime diferita de 0 octeti (-s)
if [ -f $inputFile -a -s $inputFile ]
then
#mai jos solicit utilizatorului sa introduca user/parola, VTY line password si enable secret
stty echo
echo username:
read userName
echo password:
stty -echo
read passWord
stty echo
echo VTY password:
stty -echo
read VTYpassWord
stty echo
echo ROOT/ENABLE password:
stty -echo
read RootPassWord
stty echo
#mai jos ma asigur ca s-au introdus niste valori si nu s-a apasat doar Enter
if [ "x$userName" != x -a "x$passWord" != x -a "x$VTYpassWord" != x -a "x$RootPassWord" != x ]
then
#numar cate elemente de retea sunt in total
rows=`cat $inputFile | wc -l`
#sterg continutul fisierului cu erori si al celui cu outputul comenzilor
echo > <numefisier>.error.log
echo > <numefisier>.report
#initializez un contor care imi raporteaza indexul elementului de retea la care a ajuns scriptul
i=1
#parcurg fisierul inputFile linie cu linie pana la sfarsitul acestuia
while read line
do
host=`echo $line | awk '{print $1}'`
inputCmdFile=`echo $line | awk '{print $2}'`
if [ -f $inputCmdFile -a -s $inputCmdFile ]
then
NOW=$(date +"%c")
isAlive $host $i $rows
if [ $? -eq "0" ]
then
#executabil) si outpul executiei il documentez in fisierul <numefisier>.report
./<numescriptEXPECT>.expect $inputCmdFile $host $userName $passWord $VTYpassWord $RootPassWord $NOW >> <numefisier>.report
let i++
else
echo $NOW,$host",INACCESIBILl!" >> sendCmdCisco.error.log
let i++
fi
#daca un fisier cu comenzi nu exista sau are dimensiune 0 octeti, trec la urmatorul element
else
continue
fi
done < $inputFile
#daca nu s-a introdus una valorile user/password/VTYpassword/enableSecret, se iese din script
else echo "EROARE: Nu ati introdus user/password/VTYpassword/rootpassword!"; exit 1
fi
#daca nu s-a introdus argumentul pt lansarea scriptului (cel cu datele de intrare), se iese din script
else
echo "EROARE: Verificati fisierul de intrare $inputFile !"; exit 1
fi
Scriptul scris in EXPECT (<numescriptEXPECT>.expect) arata dupa cum urmeaza:
#!/usr/local/bin/expect
#parcurg fisierul cu comenzi si introduc fiecare comanda in lista inputCmd
set inputCmd [split [read [open [lindex $argv 0] r]] "\n"]
#deschid fisierul cu erori in modul append
set errorFile [open "<numefiser>.error.log" a]
#initializez variablilele host, userName, passWord, VTYpassword, RootPassWord si recordTime
set host [lindex $argv 1]
set userName [lindex $argv 2]
set passWord [lindex $argv 3]
set VTYpassWord [lindex $argv 4]
set RootPassWord [lindex $argv 5]
set recordTime [lindex $argv 6]
#initiez sesiunea Telnet
spawn telnet $host
#daca se solicita username atunci trimit valorile variabilelor userName si apoi passWord
#daca se solicita numai parola atunci trimit valorea variabilelei VTYpassWord
#daca nu se solicita nimic timp de 10 sec atunci documentez eroarea
expect {
"*sername: " {send "$userName\n"; expect "*assword: "; send "$passWord\n"}
"*assword: " {send "$VTYpassWord\n"}
timeout {puts $errorFile "$recordTime,$host,TIMEOUT 1"; exit 1}
}
#daca nu primesc promptul specific user-EXEC (adica >) pt a trece mai departe si se solicita din nou user
#sau parola VTY atunci documentez eroarea (poate ati gresit cand ati introdus user/parola etc)
expect {
"*sername: " {puts $errorFile "$recordTime,$host,contul de acces $userName INCORECT!!!"; exit 1}
"*assword: " {puts $errorFile "$recordTime,$host,parola de acces VTY INCORECTA!!!"; exit 1}
#SUCCESS, suntem in modul user-EXEC
"*>"
}
#trimit comanda enable pt a ajunge in privileged-EXEC
send "enable\n"
#se solicita parola de escaladare a niv de privilegii (enable secret)
expect "*assword: "
#trimit valoarea variabilei care contine aceasta parola
send "$RootPassWord\n"
#daca nu primesc promptul specific priviled-EXEC (adica #) pt a trece mai departe si solicita din nou parola
#atunci documentez eroarea (poate ati gresit cand ati introdus enable secret etc)
expect {
"*>" {puts $errorFile "$recordTime,$host,parola de acces in privilegiul 15 INCORECTA!!!"; exit 1}
"*assword: " {puts $errorFile "$recordTime,$host,parola de acces in privilegiul 15 INCORECTA!!!"; exit 1}
#SUCCESS, suntem in modul privileged-EXEC
"*#"
}
#se trimite fiecare comanda din lista comenzi si apoi se inchide sesiunea Telnet,
#parasind astfel si scriptul scris in EXPECT
foreach cmd $inputCmd {
send "$cmd\n"
expect "*#"
}
exit 0
Ca sa recapitulam:
1. trebuie sa aveti instalat EXPECT
2. va trebuie fisierul <numefisier>.EXPECT - vezi mai sus
3. va trebuie fisierul <numefisier>.sh - vezi mai sus
4. va trebuie <numefisier>.csv - vezi mai sus
5. va trebuie <numefisier>.txt (atatea fisiere cate hosturi aveti, daca nu rulati aceleasi comenzi, altfel numai unul singur) - vezi mai sus
Eu am rulat cu sucess si cu BASH si cu KSH (cu mici modificari) atat din RHEL, Debian, Sun Solaris.
Spor in tot ce faceti si sper sa am vesti cat de curand pt cei care le asteapta (acum suntem cu actele la judecatorie - greu la deal cu boii mici si vale tre' sa-mpingi).
4 idei:
RăspundețiȘtergere* "let i++" poate fi pus doar o data
#daca elementul de retea nu raspunde la ping blah
else
echo $NOW,$host",INACCESIBILl!"blahblah
fi
let i++ # ca oricum fac asta
#daca un fisier cu comenzi blahblah
else
continue
fi
done < $inputFile
*cum nu se face multa procesare de intrare poate ca 'awk' e prea mult, iar 'cut' face fata
#IFS="," #nu mai e necesar acum
...
#varialbila host va contine blah
host=`echo $line | cut -d"," -f1`
#variabila inputCmdFile va contine blah
inputCmdFile=`echo $line | cut -d"," -f2`
*va trebuie un plugin ceva pentru a prezenta codul pe blog mai bine, acum arata ca un text aruncat :)
*
Multumesc pentru idei, mai ales ca le impartasiti si altora.
RăspundețiȘtergereAveti dreptate cu incrementarea variabilei i. awk mi-a venit in minte la acel moment, caci nu scriu frecvent scripturi in BASH (dar ma tratez). Intr-adevar, varianta cu cut este mult mai simpla.
Ma voi documenta sa vad cum pot scrie textul intr-un alt mod, caci recunosc ca am fost atras de ideea de a prezenta continutul si nu forma, ceea ce e o greseala atunci cand vrei sa transmiti cunostinte noi.
Acest comentariu a fost eliminat de administratorul blogului.
RăspundețiȘtergere