Monday, 15 February 2010

bash - Broken expect/TCL script -



bash - Broken expect/TCL script -

i have bash script includes expect/tcl eof script in separate function. expect script exits 0-4 possible exit codes depending on expect/tcl script determines remote device, , within if ... elif ... else statement write specific string variable depending on exit code (within expect/tcl function). command passed bash script case block runs on string contained within said variable contains.

the problem experiencing bash function contains expect/tcl script not grab exit code 3 (well can see log file entry correctly writes log file, if echo value of exit code catches 0 when situation should 3) , case statement not switching accurately.

can find bug?

(i've chopped script right downwards these parts purpose of keeping post concise , specific assume surrounding code running ok).

function mytclfunc() { /usr/bin/expect<<eof proc log_msg {msg {to_stdout no}} { set log_line "[timestamp -format {[%d/%m/%y @ %t]}] \$msg" set fh [open ~/mylogfile.log a] puts \$fh \$log_line close \$fh if {\$to_stdout} {puts \$log_line} } ;#exp_internal 1 set timeout 5 set send_human {.1 .3 1 .05 2} spawn ssh -o "stricthostkeychecking no" "[user]@$1" expect { "password: " { send -h "[my_passwd]\r" } timeout { log_msg "a relevant string log $1 / $2"; exit 1 } } set timeout 3 sleep 1 ; send -h "[command a]\r" ; expect { timeout { exit 1 } -re {\m\d{1,}(\.\d{1,}){3}\m} } if { ! [regexp {192\.[0-9]{1,3}\.{2}[0-9]{1,3}} $expect_out(0,string)]} { send -h "[command b]\r" ; } expect { "[string 1]" { send -h "[command c]\r" ; log_msg "problem f on $1 / $2" ; exit 3 } "[string 2]" { send -h "[command d]\r" ; sleep 1 ; send -h "[command e]\r" ; send -h "\r" ; puts "\r" ;#exit 0 } } expect eof eof if [[ $? -eq 0 ]]; passback="good"; elif [[ $? -eq 3 ]]; passback="bad"; else passback="timeout"; fi; } [...snipped code...] mytclfunc $myvar $1 case "$passback" in good) echo "" exit 0 ;; bad) echo "" exit 4 ;; check) echo "" exit 3 ;; esac; [...snipped code...]

the mixture of shell , tcl can bit tricky @ times. in particular, wanting deliver \ regular look engine in few places, within here-document unquoted delimiter word. fortunately, you're otherwise putting res within braces, it's just confusing , not super-confusing!

the relevant part of bash documentation says:

here documents

this type of redirection instructs shell read input current source until line containing word (with no trailing blanks) seen. of lines read point used standard input command.

the format of here-documents is:

<<[-]word here-document delimiter

no parameter expansion, command substitution, arithmetic expansion, or pathname expansion performed on word. if characters in word quoted, delimiter result of quote removal on word, , lines in here-document not expanded. if word unquoted, lines of here-document subjected parameter expansion, command substitution, , arithmetic expansion. in latter case, character sequence \<newline> ignored, , \ must used quote characters \, $, , `.

if redirection operator <<-, leading tab characters stripped input lines , line containing delimiter. allows here-documents within shell scripts indented in natural fashion.

because you're using unquoted version, want double backslashes want tcl interpreter see. in case, that's ones in regular expressions. thus, want (with above , below unchanged, think):

expect { timeout { exit 1 } -re {\\m\\d{1,}(\\.\\d{1,}){3}\\m} } if { ! [regexp {192\\.[0-9]{1,3}\\.{2}[0-9]{1,3}} $expect_out(0,string)]} { send -h "[command b]\\r" ; }

oh, , need \\r (as above) throughout script instead of \r.

i think easier split script 2 files, 1 bash code , other tcl code, @ to the lowest degree while you're developing it. you'd able create things work without having fuss around many layers of quoting. (the things you're substituting in instead passed on arguments script.)

when packaging together, bash's printf %q may helpful. it'll generate hard read, packaging operation after all…

and in relation error codes? problem there simpler; test — [[ $? -eq 0 ]] — sets error code. have save proper variable , test against that.

here, check these boiled downwards cases:

bash-3.2$ ( exit 2 ); if [[ $? -eq 0 ]]; echo ok; elif [[ $? -eq 2 ]]; echo good; else echo bad; fi bad bash-3.2$ ( exit 2 ); echo $?; if [[ $? -eq 0 ]]; echo ok; elif [[ $? -eq 2 ]]; echo good; else echo bad; fi 2 ok bash-3.2$ ( exit 2 ); code=$?; echo $code; if [[ $code -eq 0 ]]; echo ok; elif [[ $code -eq 2 ]]; echo good; else echo bad; fi 2

the first 1 approximately you're doing right now, sec shows how non-obvious can — intervening echo changes result — , 3rd shows how deal (storing value in code here, name isn't special).

bash tcl expect

No comments:

Post a Comment