| |||||||||||
global array not available in loop?? Posted by g00se (g00se), 28 July 2006 I'm using a global array inside a proc. It is readable inside the proc (even when called multiple separate times), however at the end of my loop, I want to do something with the value in the array and it complains that there is nothing in the array element when I know there should be.So I'm trying to store the current spawn_id in a global array called curr_spawn() every time I call the conn_telnet proc, so when I'm done I can gracefully exit from that particular "hop". The problem is that I can't seem to read the value of the array curr_spawn() when I'm outside of the proc. I think I took steps to make it available outside the proc so I don't understand why it isn't available?? If anyone has some time, can you please take a quick look and tell me what I'm doing wrong? It's frustrating me! Once I get this working, I can start working on compacting the code and making it a bit smarter. But first I want to get it working Thanks in advance for any help! Here's a copy of the relevant portions of the expect script: *** START OF CODE *** #!/usr/local/bin/expect set timeout 30 set argc [llength $argv] set filename [lindex $argv 0] set prompt "(#|->|\\\$) $" set iteration 0 global iteration 0 global curr_spawn() if { $argc < 1} { send_user "\nPlease specify an input file.\n" exit } proc conn_telnet {a b c} { # a = host # b = uss_pass # c = prompt # # return codes: # 0 = success # 1 = telnet not enabled on this host # 2 = unable to find server in DNS # 3 = connect timeout # 4 = invalid uss account password # 5 = unknown error spawn telnet $a puts "spawn_id = $spawn_id" global iteration global curr_spawn() set curr_spawn(iteration) "$spawn_id" puts "\n\niteration = $iteration" puts "curr_spawn(iteration) = $curr_spawn(iteration)\n\n" expect { "login:" {} "refused" { return 1 } "name not known" { return 2 } timeout { return 3 } } send "uss\r" expect "Password:" send "$b\r" expect { "login: $" { return 4 } "> " { send "e\r" expect -re $c return 0 } -re $c { return 0 } } return 5 } # main program stty -echo send_user "\nEnter current uss account password: " expect_user { timeout { send_user "\nTimeout- please restart.\n" exit } -re "(.*)\n" { set uss_pass $expect_out(1,string) } } set count 1 set file [open $filename r] foreach inputLine [split [read $file] "\n"] { if { $inputLine == "" } { puts "\nno more hosts to process." exit } set numExits 1 set exitsDone 0 #log_user 0 set line [split $inputLine ":"] set numHops [llength $line] # don't count the host we're trying to connect to # as a "hop" incr numHops -1 if { $numHops > 0 } { switch -- $numHops \ 1 { set mainHost [lindex $line 0] set hostLine [split $mainHost "|"] set hostMethod [lindex $hostLine 0] set host [lindex $hostLine 1] set hop1 [lindex $line 1] set hop1Line [split $hop1 "|"] set hop1Method [lindex $hop1Line 0] set hop1Host [lindex $hop1Line 1] send_user "\n\[$host\]: " # connect to the first hop. if { $hop1Method == "S" } { set retval [ conn_ssh $hop1Host $uss_pass $prompt ] if { $retval > 0 } { puts "ERROR: Return code $retval." continue } } else { set retval [ conn_telnet $hop1Host $uss_pass $prompt ] if { $retval > 0 } { puts "ERROR: Return code $retval." continue } } incr iteration +1 # we're connected to the first hop. Now let's connect # to the main host if { $hostMethod == "S" } { set retval [ conn_ssh $host $uss_pass $prompt ] if { $retval > 0 } { puts "ERROR: Return code $retval." continue } } else { set retval [ conn_telnet $host $uss_pass $prompt ] if { $retval > 0 } { puts "ERROR: Return code $retval." continue } } # need to send more exits to back all the way out gracefully. # Gosh, we're nice aren't we incr numExits +1 [....] removed similar code for additional hops for berevity [....] } default { puts "numHops = $numHops. only able to handle 3 hops. Find a DMZ server!!!" } } else { # we can get directly to the host without hopping around # like a damn bunny through the network. set hostLine [split $line "|"] set hostMethod [lindex $hostLine 0] set host [lindex $hostLine 1] send_user "\n\[$host\]: " if { $hostMethod == "S" } { set retval [ conn_ssh $host $uss_pass $prompt ] if { $retval > 0 } { puts "ERROR: Return code $retval." continue } } else { set retval [ conn_telnet $host $uss_pass $prompt ] if { $retval > 0 } { puts "ERROR: Return code $retval." continue } } } # need to set spawn_id to match what it was when we called the telnet # or ssh proc to connect to the box. Don't quite know why this is # important, but hey- I'm still learning puts "iteration = $iteration" puts "curr_spawn(0) = $curr_spawn(0)" puts "curr_spawn(1) = $curr_spawn(1)" set spawn_id $curr_spawn(iteration) # do your stuff, tough guy #log_user 1 send "uname -a\r" expect -re $prompt incr count +1 #log_user 0 # let's close the connections gracefully. How nice of us... while { $exitsDone < $numExits } { set spawn_id $curr_spawn(iteration) puts "iteration = $iteration" send "exit\r" expect -re $prompt incr exitsDone +1 incr iteration -1 } } *** END OF CODE *** Posted by admin (Graham Ellis), 29 July 2006 global curr_spawn() in your proc shoule read global curr_spawn. The way you have written it the variable called curr_spawn is not global within the proc, but a variable with the strange name curr_spawn() is.(and there's no need to declare a variable global in the main code - global means share this variable with the main code). Try Code:
which prints out 33 ad 40. Add () after the global aaa statement and you get 20 and 40 printed. I understand your desire to get your code working before you compact it. However, it's often much better practise to do so earlier, as it would make it mush easier for you to spot little codeing things like this, and it would make it much easier on anyone trying to help. Frankly, I'm filled with dread when I see an example that's over a page long posted and I know it's going to take me a while to spot a tiny issue that the poster could have found just by reducing the code down to show the issue in less than 30 lines as requested in Opentalk's FAQ Posted by g00se (g00se), 31 July 2006 Graham,Thank you for responding. I apologize for the lengthy code post (I'll familiarize myself with the FAQ section). I guess it was more out of frustration at not understanding how tcl handles arrays and variables in general. I'm used to declaring a variable as global at the main code level so the proc's can see them, not the other way around. I guess I need to get a different book (Exploring expect doesn't seem to have the level of detail I need). Do you have any recommendations? Posted by admin (Graham Ellis), 1 August 2006 On the Tcl side of things, the book I would personally suggest for filling you in on how things work together is Practical Programming in Tcl and Tk. On Expect, Don Libes' book that you've already mentioned contains all the facts, but little elaboration in some techniques. Perhaps there's another book to be written there, or perhaps that extra topic is too niche!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 |