Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

TCL Expect Buffer and SSH Problem?

Status
Not open for further replies.

tktuffkid

Programmer
Dec 12, 2006
11
0
0
US
I am experiencing some unexpected symptoms between Expect and SSH and was wondering if anyone could provide some insight. In a nutshell, I want to create a proc that flushes out the Expect buffer of residual characters from an SSH session. I thought of doing this by merely "expecting" a catch all regexp. However, this doesn't seem to work.

To simplify, I have provided an example below.

Given:
Prompt Format = [JohnDoe@1.2.3.4 /home]$

1) Spawn an SSH Session to server 1.2.3.4 as user JohnDoe

spawn ssh -l JohnDoe -X 1.2.3.4

2) Expect a Password prompt

expect -re {[Pp]assword:}

3) Send in JohnDoe's password

send "abc123\r"

4) Expect the User's Bash Prompt based on the given prompt format defined above. In this case, I use a regexp of a right square bracket followed by a literal dollar-sign (not an anchor)

expect -re {]\$}

5) Execute any Linux command

send "ls -al\r"

6) Execute the following two Expect commands

6a) expect -re {.*}
6b) expect -re {]\$}

My problem is that I would expect the regexp {.*} to catch everything that the spawned SSH session is returning. However, it is not. In other words, step #6a doesn't catch anything other than a single blank space (based on exp_internal debug). It's as though the SSH session does NOT want to let go and echo anything from step #5...no matter how long I wait. However, if I execute step #6b, I then see all of the output.

Can anyone tell me why the Expect command in step #6a is not catching everything? Any help would be much appreciated and thank you in advance.
 
Try a newline...and make sure that the command is received.
 
That didn't work either. With "exp_internal 1" configured, it does show the command being sent to the spawn_id.
 
Example code. This code is untested but the approach should work fine for you.

Code:
#!/usr/bin/tclsh
package require Expect

set timeout 20
set prompt1 ".*asswor.*"
set prompt2 ".*>."
#customize the above to your system

array set optarray {}

proc getopt {str lst} {
global optarray
set cnt 0

            foreach x [split $str ""] {
                      set opt "-$x"
                      if {[set ind [lsearch -exact $lst $opt]] >= 0} {
                          set optarray($opt) [lindex $lst [expr $ind + 1]]
                          incr cnt
                      }
            }
return $cnt
}

puts -nonewline "\nUsage: -d = debug, -h = host, -u = username.\n"
getopt "dhu" $argv
if {[info exists optarray(-d)]} {exp_internal 1; log_user 1}
parray optarray

if {[catch {spawn ssh $optarray(-u)@$optarray(-h)} err]} {
    send_user "Error occurred during spawn = $err\n"
    exit 1
}

expect {

       -re $prompt1 {
                    send_user "\nPassword prompt for user $optarray(-u) on host $optarray(-h): "
                    stty -echo
                    set pw [get_user]
                    stty echo
                    send "$pw\r\n"
                    exp_continue
        }

        -re $prompt2  {
                    #login successful
                    send "ls -al\r\n"
                    expect -re "(.*)\n$prompt1" {
                           send_user "Command returned information: $expect_out(1,string), $expect_out(buffer)\n"
                           close $spawn_id
                           wait
                           exit 0
                    }
        }
                                        
         timeout {send_user "$spawn_id failed to connect within $timeout seconds\n"}
         eof {send_user "Remote host closed connection.\n"}
}.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top