Search code examples
timeoutexpect

Timeout Command under Expect not Working as Expected


I'm new to this community as well as programming. I'm currently working on a an simple Expect script that that reads a file with a list of DNS names, SSH into a Cisco router, and does a simple "show ip int brief".

This list contains some hosts that are not reachable at the moment, so I'm trying to get the script to timeout that unreachable device but to continue with the rest of devices.

When I run the script, it is able to SSH to the first device and execute the "show" command. However, when it reaches the second device (which is unreachable), it hangs there for about 30 seconds and then terminates the script. I'm not sure what I'm doing wrong. Any assistance would be greatly appreciated.

#!/usr/bin/expect
#
#
set workingdir cisco/rtr
puts stdout "Enter TACACS Username:"
gets stdin tacuserid
system stty -echo
puts stdout "Enter TACACS password:"
gets stdin tacpswd
puts stdout "\nEnter enable password:"
gets stdin enabpswd
system stty echo
#
set RTR [open "$workingdir/IP-List.txt" r]
set timestamp [timestamp -format %Y-%m-%d_%H:%M]
#
while {[gets $RTR dnsname] != -1} {
if {[ string range $dnsname 0 0 ] != "#"} {
        send_user "The value of the router name is $dnsname\n"
        set timeout 10
        set count 0
        log_file -a -noappend $workingdir/session_$dnsname\_$timestamp.log
        send_log "### /START-SSH-SESSION/ IP: $dnsname @ [exec date] ###\n"
        spawn ssh -o StrictHostKeyChecking=no -l $tacuserid $dnsname
expect {

        "TACACS Password: " {send "$tacpswd\r"}
        timeout             {puts "$dnsname - failed to login"; wait;close;exp_continue}
        }
expect {
        {>}                 {send "enable\r"; send_user "on the second expect\n"}
                }
expect {
       {assword: }          {send "$enabpswd\r"}
       }
#
expect {
        "#"                 {send "show ip int brief\r"}
       }
#expect "#"
send "exit\r"
send_log "\n"
send_log "### /END-SSH-SESSION/ IP: $dnsname @ [exec date] ###\n"
log_file
        }
}
exit

Solution

  • Your first expect is doing

    expect {...
      timeout {puts "..."; wait; close; exp_continue}
    }
    

    This will match when the ssh takes over 10 seconds to connect to a host. When this matches it inevitably exits with an error (spawn id ... not open). This is because you wait for the command to end, close the spawn connection, then restart the same expect command.

    You probably meant to use continue rather than exp_continue, in order to continue with the enclosing while loop.