Expect: Difference between revisions

From ICO wiki
Jump to navigationJump to search
Mekurnik (talk | contribs)
No edit summary
Mekurnik (talk | contribs)
 
(59 intermediate revisions by the same user not shown)
Line 1: Line 1:
Koostamisel...
=Sissejuhatus=
=Sissejuhatus=


Expect on Don Libes'i poolt kirjutatud [http://en.wikipedia.org/wiki/Tcl Tcl (Tool Command Language)] laiendus, mida kasutatakse erinevate käsurea tegevuste automatiseerimiseks. Põhiliselt kasutatakse expect'i käsurealt kasutatavate inetaktiivsete rakenduste (ssh, telnet, ftp, sudo jne) automatiseerimiseks. Expect on asendamatu abimees neile, kes tahavad automatiseerida näiteks paroolide muutmist, võrguseadmete haldamist vms tegevust, mis nõuab kasutaja-terminali vahelist suhtlust.
Expect on Don Libes'i poolt kirjutatud [http://en.wikipedia.org/wiki/Tcl Tcl (Tool Command Language)] laiendus, mida kasutatakse erinevate käsurea tegevuste automatiseerimiseks. Põhiliselt kasutatakse expecti käsurealt kasutatavate interaktiivsete rakenduste (ssh, telnet, ftp, sudo jne) automatiseerimiseks. Expect on asendamatu abimees neile, kes tahavad automatiseerida näiteks paroolide muutmist, võrguseadmete haldamist vms tegevust, mis nõuab kasutaja-terminali vahelist suhtlust.
Piltlikult võib öelda, et kasutades etteantud skripti expect "räägib" teiste interaktiivsete programmidaga. Järgides skripti expect teab mida programmilt oodata ja mida programmile erinevates olukordades "öelda".  
Piltlikult võib öelda, et kasutades etteantud skripti expect "räägib" teiste interaktiivsete programmidaga. Järgides skripti expect teab mida programmilt oodata ja mida programmile erinevates olukordades "öelda".


=Üldine=
=Üldine=
Line 13: Line 12:
Interact annab juhtimise üle kasutajale.
Interact annab juhtimise üle kasutajale.


Järgneva artikli paremaks mõistmiseks peaks olema eelnevalt tuttav Linuxi käsureaga.
Järgneva artikli paremaks mõistmiseks peaks olema eelnevalt tuttav Linuxi käsureaga. <br>
Artikli koostamisel on kasutatud expecti versiooniga 5.44.1.15.


Expect interpretaatori käivitamiseks sisesta käsureale:
Expect interpretaatori käivitamiseks sisesta käsureale:
Line 25: Line 25:
=Send=
=Send=


Send käsk loeb etteantud stringi kui argumenti ja saadab selle protsessile. Näiteks:
Send käsk loeb etteantud stringi kui argumenti ja saadab selle protsessile või standard väljundisse. <br>
Näiteks:


<pre>send "tere maailm"</pre>
<pre>send "tere maailm"</pre>
Line 40: Line 41:
expect1.2> </code>
expect1.2> </code>


Kui eelnev send käsk lisada faili (nt. nimega test), saab skripti käivitada UNIXi käsurealt.  
Expecti kasutamiseks on otstarbekas kasutada skriptimist, mis on ühtlasi ka levinuim viis expecti rakendamisel.<br>
Selleks loome skriptifaili (nt. nimega test), ja lisame sinna eelmainitud send käsu. Tulemuseks saab skripti käivitada UNIXi käsurealt.  


<pre>expect test</pre>
<pre>expect test</pre>
Line 52: Line 54:
Nüüd saad skripti käivitada ka käsuga:
Nüüd saad skripti käivitada ka käsuga:
<pre>./test</pre>
<pre>./test</pre>
Edaspidiste näidete puhul tulebki kasutada expecti käivitamist failist, mitte expect interpretaatorit.


=Expect=
=Expect=
Line 65: Line 69:
Käivitme skripti  
Käivitme skripti  
<pre>./vestlus</pre>  
<pre>./vestlus</pre>  
Juhtub see, et programm ootama stringi ''tere'' ja reavahetust (\n). Kirjutades käsureale ''tere'' ja vajutades enterit väljastatakse vastuseks ''tere ise ka!''.
Juhtub see, et programm ootama stringi ''tere'' ja reavahetust (\n). Sisestades käsureale ''tere'' väljastatakse vastuseks ''tere ise ka!''.


==expect_out(0,string)/expect_out(buffer)==
==expect_out(0,string) ja expect_out(buffer)==
Expect jääb oodatavat stringi ootama seniks kuni see sisetatakse. Kui kasutada eelnevat skripti ja sisestada ''tere''asemel näiteks ''hello'' siis expect ei väljasta midagi ja jääb endiselt ootama ''tere''sisestamist. Kui sisestada lõpuks ka oodatav string (''tere'') siis expect vastab. Enne vastamist aga salvestab expect sobinud märgid muutujasse ''expect_out(0,string)''. Sobinud märgid ning lisaks kõik sellele eelnevalt sisestatud märgid salvestatakse muutujasse ''expect_out(buffer)''.
Expect jääb oodatavat stringi ootama seniks kuni see sisetatakse. Kui kasutada eelnevat skripti ja sisestada ''tere'' asemel näiteks ''hello'' siis expect ei väljasta midagi ja jääb endiselt ootama ''tere'' sisestamist. Kui sisestada lõpuks ka oodatav string (''tere'') siis expect vastab. Enne vastamist aga salvestab expect sobinud märgid muutujasse ''expect_out(0,string)''. Sobinud märgid ning lisaks kõik sellele eelnevalt sisestatud märgid salvestatakse muutujasse ''expect_out(buffer)''.
Eelnevat tehakse iga kord kui expect tuvastab sobinud märgid.
Eelnevat tehakse iga kord kui expect tuvastab sobinud märgid.


Line 79: Line 83:


Nurksulud ei ole iseenesest vajalikud aga teevad väljundi lugemise lihtsamaks - parem on aru saada kus algavad ja lõpevad muutujad.
Nurksulud ei ole iseenesest vajalikud aga teevad väljundi lugemise lihtsamaks - parem on aru saada kus algavad ja lõpevad muutujad.
Kui skript käivitada ja sisetada näiteks:
Kui skript käivitada ja sisestada näiteks:
<pre>hei, tere</pre>
<pre>hei, tere</pre>
väljastatakse tulemuseks:
väljastatakse tulemuseks:
Line 89: Line 93:
=Ankrud=
=Ankrud=


Nagu enne mainitud ei ole mittesobituva info leidmine sisendis expecti jaoks probleem. Sisendi jälgmist jätkatakse kuni sobitumiseni. Vahel on aga vaja aga piirata mittevajalike sümbolite ilmumist sisendisse.
Nagu enne mainitud ei ole mittesobituva info leidmine sisendis expecti jaoks probleem. Sisendi jälgmist jätkatakse kuni sobitumiseni. Vahel on vaja aga piirata mittevajalike sümbolite ilmumist sisendisse.


^ kasutatakse juhul kui on vaja sobitumist sisendi alguses. Näiteks ''^hei'' sobitub kui kirjutada sisendisse ''hein'' aga ei sobitu sisendiga ''juhhei''
^ kasutatakse juhul kui on vaja sobitumist sisendi alguses. Näiteks ''^hei'' sobitub kui kirjutada sisendisse ''hein'' aga ei sobitu sisendiga ''juhhei''
Line 97: Line 101:
=Timeout=
=Timeout=


Vaikimisi ootab expect sobituvat sisendit 10 sekunidit. Kui selle aja jooksul sobitumist ei toimi siis expect lõpetab.
Vaikimisi ootab expect sobituvat sisendit 10 sekundit. Kui selle aja jooksul sobitumist ei toimu siis expect lõpetab.
Loomilikult saab timeouti ka muuta. Selleks on käsk:
Loomilikult saab timeouti ka muuta. Selleks on käsk:


<pre>set timeout 60</pre>
<code>set timeout 60</code>
 
Eelnev määrab timeoudiks 60 sekundit.
Eelnev määrab timeoudiks 60 sekundit.


Line 109: Line 114:
-1 määrab, et excpect peaks ootama igavesti.
-1 määrab, et excpect peaks ootama igavesti.


=Muster-Tegevus paarid=
=Expect-Send paarid=
 
Expect-Send paaride korral kirjeldatakse Expect, mida oodatakse ja selle järele kohe Send mis peaks sobitumisel väljastatama. <br>
 
<b>Näide 1:</b>
 
<code> expect "tere" {send "$expect_out(buffer)"} </code>
 
Näide 1 puhul jääb expect ootama ''tere'' sisestamist ja kui see on sisestatud siis väljastab kogu sisestatud teksti mis sellele eelnes ja ''tere''. <br>
 
<b>Näide 2:</b>
 
<code>
expect "tere" { send "tere ise ka!\n" }\<br>
"hei" { send "hei sullegi!\n" }
</code>
 
 
Näide 2 puhul oodatakse üheaegselt nii ''tere'' kui ka ''hei'' sobitumist. Täide viiakse see send, mille ees olev expect esimesena sobitub. Kui ükski expect ei sobitu enne timeout aega siis expect lõpetab selle lause ning jätkab skripti järgmise käsu täitmisega.<br>
Expect koodis ei ole vahet kuidas expect ja send visuaalselt paigutatud on. Põhimõtteliselt võib koodi esitada ka ühe pika reana kuigi eraldi ridadel on expect-send paare parem lugeda. Silmas tuleb pidada vaid seda, et send käsud peavad olema loogeliste sulgude sees.
Eelnevas näites kasutatud \ rea lõpus tähendab seda, et käsk jätkub, st. et kui expecte oleks selles näites rohkem olnud siis peab kõigi ridade, peale viimase, lõpus olema \.
 
Sama näidet saab kujutada ka kujul:
 
<code>
expect {<br>
"tere" { send "tere ise ka!\n" }<br>
"hei" { send "hei sullegi!\n" }<br>
}<br>
</code>
 
=Spawn=
 
Spawn käsku kasutatakse protsesside välja kutsumiseks. Spawni esimene argument on protess, mida välja kutsutakse ja järnevad argumendid edastatakse väljakutsutavale protsessile.
 
<code>spawn telnet 192.168.1.254</code><br>
 
Eelnev spawn käsk kutsub välja protsessi ''telnet''. 192.168.1.254 on telneti protsessi argument. Kokkuvõttes tehakse telnet ip-le 192.168.1.254, mis võrdub samaga kui anda terminali aknasse käsk <pre>telnet 192.168.1.254</pre> Kui spawn on protsessi välja kutsunud saab protsessiga manipuleerimiseks anda juhtimise üle expectile.
 
<b>Näide 1:</b>
 
Lihtne ruuteri rebootimise skript, mis kutsub välja telnet protsessi ip-le 192.168.1.254. Seejärel logib sisse ja käsurea ilumisel sisestab käsu ''reload'' ning kinnituse.
 
<pre>
#!/usr/bin/expect
spawn telnet 192.168.1.254
expect "Username*"
send "MinuKasutajanimi\r"
expect "Password*"
send "MinuParool\r"
expect "*#"
send "reload\n"
expect "Are you sure?"
send "yes\r"
</pre>
 
==Interact==


Muster-Tegevus paare saab määratakse nii, et kirjeldatakse muster, mida oodatakse ja selle järele kohe tegevus mis peaks sobitumisel tehtama. Näiteks:
Eelnenud rebootimise näide oli täisautomaatne, st expect tegi kogu töö ilma, et kasutaja oleks saanud sekkuda. Vahel on aga vajalik, et expect annaks juhtimise üle kasutajale. Selleks kasutatakse käsku ''interact''.


<pre> expect "tere" {send "$expect_out(buffer)"} </pre>
<b>Näide 1:</b><br>
<code>#!/usr/bin/expect<br>
spawn telnet 192.168.1.254<br>
expect "Username*"<br>
send "MinuKasutajanimi\r"<br>
expect "Password*"<br>
send "MinuParool\r"<br>
interact<br>
</code>


Eelneva näite puhul jääb expect ootama ''tere'' sisestamist ja kui see on sisestatud siis väljastab kogu sisestatud teksti mis sellele eelnes ja ''tere''.
Selle näite puhul tehakse telnet, logitakse sisse ja seejärel antakse juhtimine üle kasutajale. Kasutaja on nüüd sisseloginud ja võib teha edasised toimingud.


=Muutujad=


=Koostab=
Muutujaid defineeritakse järgmiselt:
 
<code>
set <muutuja> <väärtus>
</code>
 
<b>Näide 1:</b><br>
Eelneva sisselogimise skripti saab ümber teha kasutades muutujaid järgmiselt:
 
<code>#!/usr/bin/expect<br>
set kasutajanimi Minukasutajanimi<br>
set parool Minuparool<br>
spawn telnet 192.168.1.254<br>
expect "Username*"<br>
send "$kasutajanimi\r"<br>
expect "Password*"<br>
send "$parool\r"<br>
</code>
 
Samuti on võimalik anda muutujaid kaasa käsurealt. Sellisel juhul kasutatakse muutuja väärtust ''[lindex $argv X]'', kus x on argumendi number.
 
<b>Näide 2:</b><br>
Teeme sisselogimise näite ümber selliselt, et kasutajanimi ja parool tuleb kaasa anda skripti käivitamisel. Skript käivitatakse käsuga:
<pre> ./skript minukasutajanimi minuparool </pre>
 
<code>#!/usr/bin/expect<br>
set kasutajanimi [lindex $argv 0]<br>
set parool [lindex $argv 1]<br>
spawn telnet 192.168.1.254<br>
expect "Username*"<br>
send "$kasutajanimi\r"<br>
expect "Password*"<br>
send "$parool\r"<br>
</code>
 
=Kasutatud kirjandus=
 
1. http://oreilly.com/catalog/expect/chapter/ch03.html <br>
2. http://expect.sourceforge.net/ <br>
3. man expect <br>
 
=Autor=
Meelis Kurnikov AK21
Meelis Kurnikov AK21
Viimati redigeeritud 26.12.2011
[[Category: Operatsioonisüsteemide administreerimine ja sidumine]]
[[Category: Operatsioonisüsteemide administreerimine ja sidumine]]

Latest revision as of 12:42, 5 January 2012

Sissejuhatus

Expect on Don Libes'i poolt kirjutatud Tcl (Tool Command Language) laiendus, mida kasutatakse erinevate käsurea tegevuste automatiseerimiseks. Põhiliselt kasutatakse expecti käsurealt kasutatavate interaktiivsete rakenduste (ssh, telnet, ftp, sudo jne) automatiseerimiseks. Expect on asendamatu abimees neile, kes tahavad automatiseerida näiteks paroolide muutmist, võrguseadmete haldamist vms tegevust, mis nõuab kasutaja-terminali vahelist suhtlust. Piltlikult võib öelda, et kasutades etteantud skripti expect "räägib" teiste interaktiivsete programmidaga. Järgides skripti expect teab mida programmilt oodata ja mida programmile erinevates olukordades "öelda".

Üldine

Expecti põhiliseks alustalaks on kolm käsku: expect, send ja spawn. Samuti on tihti suureks abiks käsk interact. Expect ootab teatud andmeid protsessilt. Send käsk saadab andmed protsessile. Spawn alustab protsessi. Interact annab juhtimise üle kasutajale.

Järgneva artikli paremaks mõistmiseks peaks olema eelnevalt tuttav Linuxi käsureaga.
Artikli koostamisel on kasutatud expecti versiooniga 5.44.1.15.

Expect interpretaatori käivitamiseks sisesta käsureale:

 expect 

tulemus:

expect1.1>

Send

Send käsk loeb etteantud stringi kui argumenti ja saadab selle protsessile või standard väljundisse.
Näiteks:

send "tere maailm"

Eelneva puhul saadetakse string tere maailm. Kui expect juba suhtleb mõne programmiga siis saadetakse string sellele programmile. Hetkel saadetakse see aga standard väljundisse. Kasutades expect interpretaatorit, näeks tulemus välja selline:

tere maailmexpect1.2>

Send käsk ei muuda string formaati ja seega peale selle esitamist liidetakse otsa expecti prompt. Selleks, et prompt prinditaks uuele reale on vaja lisada stringi lõppu reavahetuse sümbol \n.

send "tere maailm\n"

tere maailm
expect1.2>

Expecti kasutamiseks on otstarbekas kasutada skriptimist, mis on ühtlasi ka levinuim viis expecti rakendamisel.
Selleks loome skriptifaili (nt. nimega test), ja lisame sinna eelmainitud send käsu. Tulemuseks saab skripti käivitada UNIXi käsurealt.

expect test

Mõningase faili muutmisega saab aga skripti käivitada ka ilma expecti lisamata. Selleks lisa faili algusesse expecti asukoht:

#!/usr/bin/expect

ja muuda fail käivitatavaks:

chmod +x test

Nüüd saad skripti käivitada ka käsuga:

./test

Edaspidiste näidete puhul tulebki kasutada expecti käivitamist failist, mitte expect interpretaatorit.

Expect

Expect on vastupidine send'le. Expect ootab vastust programmilt või kasutajalt. Expect võib oodata kindlat stringi või ka osa teadaolevast stringist. Näiteks loome faili "vestlus" alloleva sisuga ja anname talle käivitamise õigused.

#!/usr/bin/expect
expect "tere\n"
send "tere ise ka!\n"

Käivitme skripti

./vestlus

Juhtub see, et programm ootama stringi tere ja reavahetust (\n). Sisestades käsureale tere väljastatakse vastuseks tere ise ka!.

expect_out(0,string) ja expect_out(buffer)

Expect jääb oodatavat stringi ootama seniks kuni see sisetatakse. Kui kasutada eelnevat skripti ja sisestada tere asemel näiteks hello siis expect ei väljasta midagi ja jääb endiselt ootama tere sisestamist. Kui sisestada lõpuks ka oodatav string (tere) siis expect vastab. Enne vastamist aga salvestab expect sobinud märgid muutujasse expect_out(0,string). Sobinud märgid ning lisaks kõik sellele eelnevalt sisestatud märgid salvestatakse muutujasse expect_out(buffer). Eelnevat tehakse iga kord kui expect tuvastab sobinud märgid.

Muudame eelneva skripti vestlus sisu järgnevaks:
#!/usr/bin/expect
expect "tere"
send "sina sisestasid <$expect_out(buffer)>"
send "oodatud string oli <$expect_out(0,string)>"


Nurksulud ei ole iseenesest vajalikud aga teevad väljundi lugemise lihtsamaks - parem on aru saada kus algavad ja lõpevad muutujad. Kui skript käivitada ja sisestada näiteks:

hei, tere

väljastatakse tulemuseks:


sina sisestasid <hei, tere>
oodatud string oli <tere>

Ankrud

Nagu enne mainitud ei ole mittesobituva info leidmine sisendis expecti jaoks probleem. Sisendi jälgmist jätkatakse kuni sobitumiseni. Vahel on vaja aga piirata mittevajalike sümbolite ilmumist sisendisse.

^ kasutatakse juhul kui on vaja sobitumist sisendi alguses. Näiteks ^hei sobitub kui kirjutada sisendisse hein aga ei sobitu sisendiga juhhei

$ kasutatakse juhul kui on vaja sobitumist sisendi lõpus. Näiteks hei$ sobitub sisendiga juhhei kuid mitte hein. Järelikult ^hei$ ei sobitu kummagagi, vaid ainult hei'ga.

Timeout

Vaikimisi ootab expect sobituvat sisendit 10 sekundit. Kui selle aja jooksul sobitumist ei toimu siis expect lõpetab. Loomilikult saab timeouti ka muuta. Selleks on käsk:

set timeout 60

Eelnev määrab timeoudiks 60 sekundit.

Üldiselt peab olema timeout positiivne arv. On aga paar erandit.

0 määrab, et expect ei peaks ootama üldse.

-1 määrab, et excpect peaks ootama igavesti.

Expect-Send paarid

Expect-Send paaride korral kirjeldatakse Expect, mida oodatakse ja selle järele kohe Send mis peaks sobitumisel väljastatama.

Näide 1:

expect "tere" {send "$expect_out(buffer)"}

Näide 1 puhul jääb expect ootama tere sisestamist ja kui see on sisestatud siis väljastab kogu sisestatud teksti mis sellele eelnes ja tere.

Näide 2:

expect "tere" { send "tere ise ka!\n" }\
"hei" { send "hei sullegi!\n" }


Näide 2 puhul oodatakse üheaegselt nii tere kui ka hei sobitumist. Täide viiakse see send, mille ees olev expect esimesena sobitub. Kui ükski expect ei sobitu enne timeout aega siis expect lõpetab selle lause ning jätkab skripti järgmise käsu täitmisega.
Expect koodis ei ole vahet kuidas expect ja send visuaalselt paigutatud on. Põhimõtteliselt võib koodi esitada ka ühe pika reana kuigi eraldi ridadel on expect-send paare parem lugeda. Silmas tuleb pidada vaid seda, et send käsud peavad olema loogeliste sulgude sees. Eelnevas näites kasutatud \ rea lõpus tähendab seda, et käsk jätkub, st. et kui expecte oleks selles näites rohkem olnud siis peab kõigi ridade, peale viimase, lõpus olema \.

Sama näidet saab kujutada ka kujul:

expect {
"tere" { send "tere ise ka!\n" }
"hei" { send "hei sullegi!\n" }
}

Spawn

Spawn käsku kasutatakse protsesside välja kutsumiseks. Spawni esimene argument on protess, mida välja kutsutakse ja järnevad argumendid edastatakse väljakutsutavale protsessile.

spawn telnet 192.168.1.254

Eelnev spawn käsk kutsub välja protsessi telnet. 192.168.1.254 on telneti protsessi argument. Kokkuvõttes tehakse telnet ip-le 192.168.1.254, mis võrdub samaga kui anda terminali aknasse käsk

telnet 192.168.1.254

Kui spawn on protsessi välja kutsunud saab protsessiga manipuleerimiseks anda juhtimise üle expectile.

Näide 1:

Lihtne ruuteri rebootimise skript, mis kutsub välja telnet protsessi ip-le 192.168.1.254. Seejärel logib sisse ja käsurea ilumisel sisestab käsu reload ning kinnituse.

#!/usr/bin/expect
spawn telnet 192.168.1.254
expect "Username*"
send "MinuKasutajanimi\r"
expect "Password*"
send "MinuParool\r"
expect "*#"
send "reload\n"
expect "Are you sure?"
send "yes\r"

Interact

Eelnenud rebootimise näide oli täisautomaatne, st expect tegi kogu töö ilma, et kasutaja oleks saanud sekkuda. Vahel on aga vajalik, et expect annaks juhtimise üle kasutajale. Selleks kasutatakse käsku interact.

Näide 1:
#!/usr/bin/expect
spawn telnet 192.168.1.254
expect "Username*"
send "MinuKasutajanimi\r"
expect "Password*"
send "MinuParool\r"
interact

Selle näite puhul tehakse telnet, logitakse sisse ja seejärel antakse juhtimine üle kasutajale. Kasutaja on nüüd sisseloginud ja võib teha edasised toimingud.

Muutujad

Muutujaid defineeritakse järgmiselt:

set <muutuja> <väärtus>

Näide 1:
Eelneva sisselogimise skripti saab ümber teha kasutades muutujaid järgmiselt:

#!/usr/bin/expect
set kasutajanimi Minukasutajanimi
set parool Minuparool
spawn telnet 192.168.1.254
expect "Username*"
send "$kasutajanimi\r"
expect "Password*"
send "$parool\r"

Samuti on võimalik anda muutujaid kaasa käsurealt. Sellisel juhul kasutatakse muutuja väärtust [lindex $argv X], kus x on argumendi number.

Näide 2:
Teeme sisselogimise näite ümber selliselt, et kasutajanimi ja parool tuleb kaasa anda skripti käivitamisel. Skript käivitatakse käsuga:

 ./skript minukasutajanimi minuparool 

#!/usr/bin/expect
set kasutajanimi [lindex $argv 0]
set parool [lindex $argv 1]
spawn telnet 192.168.1.254
expect "Username*"
send "$kasutajanimi\r"
expect "Password*"
send "$parool\r"

Kasutatud kirjandus

1. http://oreilly.com/catalog/expect/chapter/ch03.html
2. http://expect.sourceforge.net/
3. man expect

Autor

Meelis Kurnikov AK21

Viimati redigeeritud 26.12.2011