Andy Thompson
Andy Thompson

Reputation: 304

Expect script failed with "spawn id not open" when calling "expect eof"

I am trying to call an expect script from bash and have it return exit code in case of e.g. Connection Timeout.

Basically the bash script is calling expect like this:

if [[ -f $1 ]]; then
    do something
else
    script.exp $device
    # here I want to evaluate the exit code but it is always 0
fi

I found some previous questions about it and that the right way to catch exit codes is:

expect eof
catch wait result
exit [lindex \$result 3].

The expect script:

#!/usr/bin/expect

exp_internal 1
log_user 1
set timeout -1
set hostname [lindex $argv 0]
set prompt "sftp>";

if { $hostname == "blah" } {
        set username "user1"
        set password "pass1"
} else {
        set username "user2"
        set password "pass2"
}

spawn sftp $username@$hostname "-o ConnectTimeout=3"

expect {
    "timeout" {
        puts "A timeout occured"
        exp_continue
    }
    "password:" {
         send "$password\r"
         exp_continue
    }
    "sftp>" {
         send "cd cfg\n"
         expect $prompt
         send "get * /some/dir/$hostname\n"
         expect $prompt
         send "get running-config /some/dir/$hostname-config\n"
         expect $prompt
         send "exit\r";
         exp_continue
    }
}
expect eof
catch wait result
exit [lindex \$result 3]

When I just test the expect script to see what happens, I get this error:

expect: spawn id exp4 not open
    while executing
"expect eof"

I've tried moving expect eof around but it does not change the behavior. It states that the spawned process id is not open, which I guess is correct as it has exited with Timed Out/Connection closed?

Upvotes: 0

Views: 2149

Answers (2)

  1. Remove exp_continue after send "exit\r", otherwise EOF will be consumed by the expect { ... } block and another expect eof would fail.
  2. Change lindex \$result 3 to lindex $result 3 as in the comments.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 246764

(Incorporating the previous comments)
Add it into the previous expect command, but with no body:

expect {
    timeout   {...}
    password: {...}
    sftp>     {...}
    eof
}
wait result
if {[lindex $result 2] == 0} {
    exit [lindex $result 3]
} else {
    error "system error: errno [lindex $result 3]"
}

Upvotes: 0

Related Questions