Training, Open Source computer languages
PerlPHPPythonMySQLApache / TomcatTclRubyJavaC and C++LinuxCSS 
Search for:
Home Accessibility Courses Diary The Mouth Forum Resources Site Map About Us Contact
 
For 2023 (and 2024 ...) - we are now fully retired from IT training.
We have made many, many friends over 25 years of teaching about Python, Tcl, Perl, PHP, Lua, Java, C and C++ - and MySQL, Linux and Solaris/SunOS too. Our training notes are now very much out of date, but due to upward compatability most of our examples remain operational and even relevant ad you are welcome to make us if them "as seen" and at your own risk.

Lisa and I (Graham) now live in what was our training centre in Melksham - happy to meet with former delegates here - but do check ahead before coming round. We are far from inactive - rather, enjoying the times that we are retired but still healthy enough in mind and body to be active!

I am also active in many other area and still look after a lot of web sites - you can find an index ((here))
Timing output capture

Posted by jltttran (jltttran), 12 December 2007
Hello,

I wrote a tcl script that ssh into a cisco router and capture the show command output.  The output is long, and I am only able to capture about 1/5 of the total output if I tweak the timer delay to 10.  If timer is set to 1 then I capture nothing.  

I'd like to get some advise on how to adjust the timer value or get a different perspective on solving this problem.

Thanks in advance.
-Catherine

Posted by jltttran (jltttran), 12 December 2007

Sending you some snippets of my code:

proc timez { time_delay_seconds } {
       set hour [exec date +%l]
       set minute [exec date +%M]
       set second [exec date +%S]
       set temp_current [concat $hour$minute$second]

       set projected_timer [expr $temp_current + $time_delay_seconds]

       while {$projected_timer > $temp_current} {
             set hour [exec date +%l]
             set minute [exec date +%M]
             set second [exec date +%S]
             set temp_current [concat $hour$minute$second]
       }
}

set file [open $routerlist "r"]
while {[gets $file router] >= 0} {

   exp_spawn ssh -l $login $router
   expect {
     "password: " {
         send "$password\r"
     }
   }

   expect "#"
   send "term len 0\r"

   set command_file [open $commands]
   set command [gets $command_file]


   ## While traversing the commands send it to the router until the list ends
   while {![eof $command_file]} {  

     expect "#"

     send_log "\n ------  Subcommand: [string toupper $command] ----- \n"
     send "$command\r"

     ## Calling timez proc for X seconds delay before next command
     timez $time_value_from_command_file

       set command [gets $command_file]
     expect "#"
     send "$command\r"
   
 }

 send "exit\r"
}

Posted by admin (Graham Ellis), 12 December 2007
Expect's buffers can be a bit small.  Usual solution is to expect line by line (delimiting at \n) and process as you get the output, or use lappend to build a list of responses if you want to process it all at once.

Posted by jltttran (jltttran), 18 December 2007

Thank you for your reply.  Could you show by using a brief example how to do this?

Thanks.
-Catherine

Posted by admin (Graham Ellis), 19 December 2007
Yes ... have a look at the next thread along:

http://www.wellho.net/cgi-bin/opentalk/YaBB.pl?board=tcl;action=display;num=1197682409

Posted by jltttran (jltttran), 27 December 2007

Hi Graham,

Thanks for the pointer, that helps a lot.   Another problem I have related to timing is pushing out the router password in time when router prompts for it.  


set timeout 11

while {[gets $file router] >= 0} {
 
   spawn ssh -l login_name $router

   expect {
        "password: " {
             send "$password\r"
           }

   }
 
   expect "#" {send "term len 0\r"}

   .....



Posted by jltttran (jltttran), 27 December 2007
sorry, I fat-fingered and posted an unfinished reply.

Anyway, I  currently use "set timeout 11" to tell the script to wait for some time before feeding the passwd, otherwise the script would process pass the 'expect { "password: " ...' , feed in other strings, and fail to access the router.

Is there a way that would work every time (may be a while loop of some sort )  to pace for the right time to feed in the password since 'set timeout 11' is a guess, and this value is different for different router

Thanks.
-Catherine


Posted by admin (Graham Ellis), 28 December 2007
There's no easy answer to the question "how long should my timeout be?".

You need, I'm sorry, to work it out by guesswork unless there's something in the specification of the remote system that tells you how long it will take; too short a time, and you'll end up prematurely shutting down the connection, too long and you'll wait beyond what you should to inform the user of a failure.   I hope that your timeout is only a safety net though - so it shouldn't matter too much!

Posted by jltttran (jltttran), 28 December 2007

I'd have to be creative to come up with a way to set the right time out for each router if my script has to access a list of router, one after another.

Thank you very much for your help.
-Catherine

Posted by swalia (swalia), 29 December 2007
I had faced a similar problem and I got a solution for you
It is very powerful, I use it for automating upgrades of Images on routers and what not.

create a function which I call wait_for, here it is

proc wait_for {wait_for_what} {
set expect_out(0,string) junk
while {$expect_out(0,string) != "$wait_for_what"} {
expect $wait_for_what
}
}

and here is how I use it,

spawn telnet 192.168.128.10
wait_for "password"
send "enable_password"

This will wait infinitely till you get the password:



Posted by admin (Graham Ellis), 29 December 2007
on 12/29/07 at 05:33:20, swalia wrote:
This will wait infinitely till you get the password:


Indeed it will. So if your router is switched off or unplugged, you've just started a process that will hang for ever.  That might be what you want to do swalia, but in most circumstances programs that go into an infinite loop without any time out option at all are not a good idea!

Posted by swalia (swalia), 29 December 2007
With a little tweaking one can avoid the infinite wait. For a switched off router one can define a max time the script should try to connect before giving up. This can be done either by 'time' or number of 'expect' attempts, here is an example will number of attempts.

proc wait_for {value max_iterations} {

set expect_out(0,string) junk
set wait_iterations 0
while {$expect_out(0,string) != "$value"} {
expect $value { break }

if {$wait_iterations < $max_iterations } {
incr wait_iterations
} else {
puts "Upper limit for wait expired, Device which you are trying to connect is not responding, quitting"
exit
}
}
}

Here is how it would go without waiting infinitely,

spawn telnet 192.168.128.1
wait_for password: 5

in the above case the maximum wait time will be 5 x timeout i.e. 50 sec assuming the timeout to be 10sec. If the router doesn't respond in 50 sec the script will exit and you can start troubleshooting the physical connectivity. On the otherhand if the router is up and properly connected, the script will not have to wait extra and will continue gracefully.

Please point out any shortcoming(s) of the script.

Best
swalia

Posted by admin (Graham Ellis), 30 December 2007
Unless you want to take other actions every 10 seconds of waiting, what does this code gain above setting the expect variable timeout?

set timeout 50



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.

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2024: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho