Training, Open Source computer languages

This is page http://www.wellho.net/forum/The-Tcl- ... guage/running-multiple-ssh-instances-asynchronously.html

Our email: info@wellho.net • Phone: 01144 1225 708225

 
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))
running multiple ssh instances asynchronously?

Posted by that_guy (that_guy), 21 July 2003
I'm writing a network monitor script that uses ssh to connect to ~40 machines and retrieve the contents of their routing tables using expect+ route -n. Right now I have a loop that goes through a list of currently available hosts. The problem is that doing this sequentially is very slow- it takes about 7 minutes to finish. Is there some reasonably simple way to run this part of the script on several machines at once in parallel? This is what the fragment of code currently looks like:

 foreach item $::libextreme::vlans {
           set ::libextreme::vlan_info($item,ports) [eval ::libextreme::get_vlan_ports [lrange "$item online" 0 end]]
               foreach thing [::libextreme::get_vlan_hosts $item online] {
                   if {[catch {set ::libextreme::routes($thing) [::libextreme::get_routes $thing online ] }  err] } {
                       send_user "something's wrong with $thing\n"
                   }
               }
       }

get_routes is the procedure that sshs to machine runs 'route -n' and returns a list of routes. I've included it below:

proc ::libextreme::get_routes {hostname mode} {
   if {[string compare $::libextreme::mode online] == 0} {
   variable prompt
   set timeout 2
   set ipaddr "\[0-9]+\.\[0-9]+\.\[0-9]+\.\[0-9]+"
   stty -echo
   spawn ssh $hostname
   expect "*"
   if { [string compare $hostname unknown] != 0} {
       expect -re "\[\n\r\t ]*$prompt(node,$hostname)"
   }
   exp_send "su\r"
   expect "Password:"
   exp_send "mypassword\r"
   expect -re "\[\n\r\t ]*$hostname:/home/$user#"
   exp_send "route -n\r"
   expect "\n"
   expect -re ".*Iface\r\n"
   set num 0
   #+\[\t ]\[0-9]\[\t ]\[0-9]\[\t ]\[0-9]\[\t ]\[a-zA-Z0-9]+
   set routes {}
   expect {
       -re "($ipaddr)\[\t ]*($ipaddr)\[\t ]*($ipaddr)\[\t ]*(\[a-zA-Z]*)\[\t ]*(\[0-9]+)\[\t ]*(\[0-9]+)\[\t ]*(\[0-9]+)(\[a-z 0-9]*)\r\n" {
           lappend routes $expect_out(buffer)
#send_user "row$num: $expect_out(buffer) endrow\n"
           incr num
           exp_continue
       }
   }


Posted by admin (Graham Ellis), 21 July 2003
We had a similar problem in checking out a network of machines for training courses - we want to plug together anything from 2 to 20 machines and have a display come up in seconds to tell us which are there.

Solution:
* spawn ping processes in a loop
* save the spawn_id into an array, and add it to a list too
* when all the pings have been started, use the expect  command with the -i option to wait for the next line back from any one of the pings
* keep repeating the previous step, noting down how many lines of response have come back from each ping

This way, all the processes are timing out in parallel rather than serially, which I think is wha you're looking for.

Complete code of our program (64 lines, I think, when I last counted) at http://www.wellho.net/cgi-bin/net/sample.pl?which=tkpingle;  it also gives you a graphic display through tk to show you the progress ... very pretty too.

[Edited to correct typing error in link]

Posted by that_guy (that_guy), 22 July 2003
Thanks a lot, I found tkpingle to be a very useful example, I'm retooling my ssh script.  I also have a part of the script that uses fping to check all the hosts, but I think I'm going to change it over to use tkpingle.
Just so you know, the link above is not functional.

[Link corrected, 05:55 - Graham]

Posted by that_guy (that_guy), 22 July 2003
hi, just wanted to work things through a bit more- if you don't mind. the script I posted at the top of the page has a lot of sequential expect statements-> i.e. when dealing with one process at a time, first wait for a null character, then wait for a new line, then wait for a prompt, then send command, then wait for prompt,etc. Now that I'm trying to do this for multiple processes by expect  -i $idlist I'm not sure how to get the same sort of sequential behaviour, as it stands right now I'm getting weird matching behaviour- I'm sure I just need to think this through a bit more- if you could comment on what I've tried so far I'd greatly appreciate it :
     cleaning this up...

Posted by admin (Graham Ellis), 22 July 2003
Quote:
Now that I'm trying to do this for multiple processes by expect  -i $idlist I'm not sure how to get the same sort of sequential behaviour


You won't get the same sort of sequential behaviour - you'll need to  "expect -i"  for any of the possible sequences (use a regular expression that looks for any possibilities),.  When you find which id the result came back from, update an array of state variables as appropriate and loop on the "expect -i".  I would only expect to see one "expect -i" in the loop.

Posted by that_guy (that_guy), 22 July 2003
I'm currently trying to do something like what I have below. Whenever some pattern arrives I move the responible spawnid into a new "stage"  and then only check members of a given stage for a certain pattern. My problem now is that in the last stage, for a given host I need to match several times- there could multiple routes in the routing table.  and I need to quit somehow. When dealing with one process, this sequence was in a loop and as soon as I timed out, I would break, because there were no early stages where things would time out.  I would greatly appreciate any suggestions as how to get the multiple matches here and be able to quit properly.  The lines below are my current final stage

         -i stage6 -re "($ipaddr)\[\t ]*($ipaddr)\[\t ]*($ipaddr)\[\t ]*(\[a-zA-Z]*)\[\t ]*(\[0-9]+)\[\t ]*(\[0-9]+)\[\t ]*(\[0-9]+)(\[a-z 0-9]*)\r\n" {
           lappend ::libextreme::routes($backlook($expect_out(spawn_id))) $expect_out(buffer)
               lappend routes $expect_out(buffer)
            }
         







Posted by admin (Graham Ellis), 23 July 2003
I think you can probably still time out  

If you spawn a whole series of sessions off,  and each of them only times out when completed, then the one and only situtation when you'll time out is when every one of them has been completed, isn't it?

Posted by that_guy (that_guy), 23 July 2003
thanks. I got things working, although one weird thing I noticed is that although I am using the same exact sort of tk popup as in tkpingle, it's highly variable when the toplevel window actually pops up- usually not until all the processes are almost done.  I am guessing that maybe spawning ssh is more of a strain than spawning ping, and the computer has trouble redrawing(?)
as you can see-- it's just something identical to tkpingle
proc ::libextreme::tk_route {systems} {
     toplevel .route
     set high [expr [llength $systems] * 32 + 64]
     wm geometry .route 400x$high

     foreach system $systems {
         label .route.la_$system -text $system  
           pack .route.la_$system -expand true -fill x -padx 5 -pady 5
     }
   
   .route config -background white

Posted by admin (Graham Ellis), 23 July 2003
Tk only updates the display when it has nothing else left to do and is waiting for events - this apparently curious behaviour is to avoid it doing huge numbers of redraws as you build up your graphic in the first place, or as you make a series of changes which would cause a huge amount of display activity if the display was amended once for each change.

It might be a good idea for you to add in an
      update idletasks
at some point(s) to have it update the screen from time to time.

Tkpingle doesn't exhibit the same problem because there's a good gap between returned lines, so it *does* go idle waiting for events quite frequently.




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.

© 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