| |||||||||||
expect script writing partial output to the file Posted by manicisco (manicisco), 20 July 2007 Hi experts,Below is my script.I m trying to get the show spanning-tree output from a list of devices and capture it in a file.But when I run the below script it just writes terminal length 0 hostname> I tried moving the set input filename command to many places.But still no luck.Any help on this would be appreciated. package require Expect set routerpwd removed for security reasons set password removed for security reasons set targetrouters [list removed for security reasons] set target removed for security reasons spawn ssh -l removed for security reasons $target expect -re "password:" exp_send "$password\r" expect "removed for security reasons" { foreach x $targetrouters { exp_send "ssh -l removed for security reasons $x\r" expect "(yes/no)?" exp_send "yes\r" expect "word: " exp_send "$routerpwd\r" expect ">" { exp_send "terminal length 0\r" expect ">" { exp_send "show spanning-tree\r" expect ">" set input [open output.txt a] set output $expect_out(buffer) puts $input $output exp_send "exit\r" close $input } } expect } expect -re "bgohjee@last-call-2%" { exp_send "exit\r" } } Posted by admin (Graham Ellis), 21 July 2007 I am seeing nested ssh-es and nested expects - not the easiest of codes to debug. Why are you using nexted ssh-es? Is it because you can't reach the targetrouters directly from the system running the script? If so, fair enough. I'm more worried about the nested expects. I think you would do better to complete one send / expect par and then start a fresh one. Posted by cwjolly (cwjolly), 24 August 2007 You have a number of problems. For instance typically it is very difficult to spawn another interactive program on another host since you cannot really determine if your spawn or the program you are runnin on the remote host is the cause of a timeout. A better idea would be to have the expect script on the host that you initially login to and avoid the double layer. Simply by using the ssh remoute comand feature like so. ssh -l <user > $targethost routerspanningtreeexpectscript Also don't loop inside of an expect loop which is what you are doing. It is better to ensure you have logged into the host then loop around an expect. I have re-written your program but not tested it. Try it out and let us know how it works. package require Expect set routerpwd <removed for security reasons> set password <removed for security reasons> set targetrouters <list removed for security reasons> set target <removed for securityreasons > set pid [spawn ssh -l <user removed for security reasons> $target ] set my_id $spawn_id # loop version of expect use exp_continue to loop nothing to break out expect -i $my_id { -re {[Pp]assword: } { # not use {} when you can also space after : in password prompt # NOT having space can fire your password prematurely resulting # in failure exp_send "$password\r"; exp_continue; } -re {yes/no\?} { exp_send "yes\r" exp_continue; } -re "$prompt" { send_user "Successfully logged in... Starting to collect router data" # do not use exp_continue this will automatically break out of loop } timeout { set msg "timeout" if { [ info exists expect_out(buffer) ] } { set msg $expect_out(buffer); } send_user "Unable to login to target $target\n$msg" set bad 1 } eof { set msg "premature eof" if { [ info exists expect_out(buffer) ] } { set msg $expect_out(buffer); } send_user "Unable to login to target $target\n$msg" set bad 1 } } if { $bad } { exit 1 } # now ssh to other routers. set prompt2 ">" set data "" set outputfd [open "treefile" "r" 0666 ] ; foreach x $targetrouters { set data "" set count 0 exp_send "ssh -l <user removed for security reasons> $x\r" set inClientSSH 1 expect -i $my_id { -re {word: } { # not use {} when you can also space after : in password prompt # NOT having space can fire your password prematurely resulting # in failure exp_send "$password\r"; exp_continue; } -re {yes/no\?} { exp_send "yes\r" exp_continue; } -re "$prompt" { send_user "Completed data collection on $x" set inClientSSH 0 } -re "$prompt2" { switch -exact -- $count{ 0 { send_user "Successfully logged in...to $x Starting to collect router data" exp_send -i $my_id "terminal length 0\r" incr count } 1 { exp_send -i $my_id "show spanning-tree\r" incr count } default { puts $outputfd "[string trimright $expect_out(buffer) "\n >"]"; exp_send -i $my_id "exit\r" } } } timeout { # different because other ssh session may be causing it if { $inClientSSH} { exp_send "\003" ; # send a control c to kill client ssh send_user "Comms with host $x timed out trying to recover" set inClientSSH 0 ; exp_continue; set msg $expect_out(buffer); } else { send_user "Original ssh seems to have timedout" set bad 1 } } eof { set msg "premature eof" if { [ info exists expect_out(buffer) ] } { set msg $expect_out(buffer); } send_user "Unable to login to target $target\n$msg" set bad 1 } } catch { close $outputfd } if { $bad } { exit 1; } exp_send "exit\r"; after 2000; exec kill $pid; # just to be sure set exitstatus [ exp_wait -i $my_id ]; catch { exp_close -i $my_id }; } Posted by cwjolly (cwjolly), 24 August 2007 an exp_continue is needed at this point in code.... default { puts $outputfd "[string trimright $expect_out(buffer) "\n >"]"; exp_send -i $my_id "exit\r" } } } timeout { .... change to: .... default { puts $outputfd "[string trimright $expect_out(buffer) "\n >"]"; exp_send -i $my_id "exit\r" } } exp_continue; } timeout { .... This page is a thread posted to the opentalk forum
at www.opentalk.org.uk and
archived here for reference. To jump to the archive index please
follow this link.
|
| ||||||||||
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho |