Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[expect] How to detect if process is closed from interact command

1,723 views
Skip to first unread message

Ian Petts

unread,
Oct 16, 2007, 9:29:35 PM10/16/07
to
I have an expect script that spawns an ssh connection to a remote machine, runs
several commands and then logs out. I've written a small procedure to handle
exceptions (via timeout) that prompts the user and enters interactive mode.

A simplified version of the script is below:

=== 8< ===
#!/usr/local/bin/expect --

set prompt {$ }
set box $argv
set user ian

expect_after timeout go_interactive
expect_after eof exit

proc go_interactive {} {
send_user "

*** Unexpected output from child process ***
Entering interactive mode.
Press \"+\" to return

"
interact "+" return
expect eof { exit }
return
}

spawn ssh $user@$box

expect "password:" { send "$password\r" }
expect $prompt { send "ls\r" }
expect $prompt { send "logout\r" }
expect eof
=== >8 ===

The problem I am having is that I cannot seem to gracefully catch if the user
has terminated the ssh session. I get a complaint from the script of "expect:
spawn id exp4 not open". Neither the "expect_after eof exit", nor the "expect
eof { exit }" lines seem to do the trick.

How do I detect if a spawned process is closed from within the interact
command?

Thanks,
Ian.

Glenn Jackman

unread,
Oct 17, 2007, 10:04:16 AM10/17/07
to
At 2007-10-16 09:29PM, "Ian Petts" wrote:
> I have an expect script that spawns an ssh connection to a remote machine, runs
> several commands and then logs out. I've written a small procedure to handle
> exceptions (via timeout) that prompts the user and enters interactive mode.
[...]

> How do I detect if a spawned process is closed from within the interact
> command?

As I understand it, you know the spawned process has terminated when the
interact command returns control to your script. It's that simple.

--
Glenn Jackman
"You can only be young once. But you can always be immature." -- Dave Barry

Ian Petts

unread,
Oct 17, 2007, 7:22:38 PM10/17/07
to
On 2007-10-17, Glenn Jackman <gle...@ncf.ca> wrote:
> At 2007-10-16 09:29PM, "Ian Petts" wrote:
>> How do I detect if a spawned process is closed from within the interact
>> command?

> As I understand it, you know the spawned process has terminated when the
> interact command returns control to your script. It's that simple.

Thanks Glenn, but I don't think this is correct.

Firstly, I can end the interact command and return control to the script
by using the escape character ("+" in my previous example) and secondly
if the ssh session is logged out of while in interactive mode, expect
terminates with an error rather than exiting cleanly.

Glenn Jackman

unread,
Oct 18, 2007, 10:02:53 AM10/18/07
to

I don't see what you're seeing:

expect1.1> spawn ssh somehost
spawn ssh somehost
18449
expect1.2> interact
xx087@somehost's password:
Last login: Thu Oct 18 09:57:33 2007 from thishost
Sun Microsystems Inc. SunOS 5.8 Generic Patch October 2001
# exit
logout
Connection to somehost closed.
expect1.3> wait
18449 exp6 0 0

No error.

Let's try killing the ssh session

expect1.4> spawn ssh somehost
spawn ssh somehost
18469
expect1.5> interact
xx087@somehost's password:
Last login: Thu Oct 18 09:58:33 2007 from thishost
Sun Microsystems Inc. SunOS 5.8 Generic Patch October 2001

[... in another shell, "kill 18469"...]

# Killed by signal 15.
expect1.6> wait
18469 exp6 0 255

No error.

Do you have a signal handler perhaps? Does it throw the error?

Ian Petts

unread,
Oct 18, 2007, 9:02:11 PM10/18/07
to
On 2007-10-18, Glenn Jackman <gle...@ncf.ca> wrote:
> I don't see what you're seeing:
>
> expect1.1> spawn ssh somehost
> spawn ssh somehost
> 18449
> expect1.2> interact
> xx087@somehost's password:
> Last login: Thu Oct 18 09:57:33 2007 from thishost
> Sun Microsystems Inc. SunOS 5.8 Generic Patch October 2001
> # exit
> logout
> Connection to somehost closed.
> expect1.3> wait
> 18449 exp6 0 0
>
> No error.
[...]

> Do you have a signal handler perhaps? Does it throw the error?

No, but hopefully this can demonstrate what I'm encountering:

===== 8< Example script: ex.exp >8 =====
#!/usr/bin/expect --

set timeout 5
set prompt {~% }

proc get_secret { prompt } {
stty -echo
send_user "$prompt"
expect_user -re "(.*)\n"
send_user "\n"
set secret $expect_out(1,string)
stty echo
return $secret
}

set password [ get_secret "password: " ]

spawn ssh ian@localhost


expect {
"password:" { send "$password\r" }

"continue connecting (yes/no)?" {
send "yes\r"


expect {
"password:" { send "$password\r" }
}
}
}

expect $prompt
send_user "\n\n*Entering interactive mode*\n\n"
interact

send {echo "Script logging out\r"}


send "logout\r"
expect eof

exit 0
===== 8< End >8 =====

[ian@localhost]~% ./ex.exp
password:
spawn ssh ian@localhost
ian@localhost's password:
Last login: Fri Oct 19 10:37:59 2007 from localhost.localdomain
[ian@localhost]~%

*Entering interactive mode*

[ian@localhost]~% ls
Desktop dl Documents ex.exp Music tmp

[ian@localhost]~% logout
Connection to localhost closed.
send: spawn id exp8 not open while executing "send {echo "Script logging
out\r"}" (file "./ex.exp" line 33)

Glenn Jackman

unread,
Oct 18, 2007, 11:05:14 PM10/18/07
to
At 2007-10-18 09:02PM, "Ian Petts" wrote:
[...]

> send_user "\n\n*Entering interactive mode*\n\n"
> interact
>
> send {echo "Script logging out\r"}
> send "logout\r"
> expect eof
> exit 0
> ===== 8< End >8 =====
[...]

> *Entering interactive mode*
>
> [ian@localhost]~% ls
> Desktop dl Documents ex.exp Music tmp
>
> [ian@localhost]~% logout
> Connection to localhost closed.
> send: spawn id exp8 not open while executing "send {echo "Script logging
> out\r"}" (file "./ex.exp" line 33)

I don't have my Exploring Expect book handy. The first thing that comes
to mind is:

interact

catch {
puts "Script logging out" ;# do you need the remote machine to do this?


send "logout\r"
expect eof
}

That's Tclish but it strikes me as not too Expectish. I'll have another
look in the morning.

Glenn Jackman

unread,
Oct 19, 2007, 11:21:52 AM10/19/07
to
At 2007-10-18 09:02PM, "Ian Petts" wrote:
> spawn ssh ian@localhost
[...]

> send_user "\n\n*Entering interactive mode*\n\n"
> interact
>
> send {echo "Script logging out\r"}
> send "logout\r"
> expect eof

Because you call interact without giving a key sequence to return
control to the script, the interact command cannot return unless the
interacting user ends the ssh session. So there's no point for the
script to attempt send a logout command -- the ssh session cannot still
be open after the interact command returns.

If you want to be able to interact for a while, return control to the
script, interact again, etc, there are factilities in expect to allow
that.

send_user "\n\n*Entering interactive mode*\n\n"

send_user "(type \"~x\" to end your interaction)\n\n"

set ssh_open 1

interact {
~x { return }
-o eof { set ssh_open 0; return }
}

if {$ssh_open} {
send_user "ssh session still open: script logging out\n"


send "logout\r"
expect eof
}

--

Ian Petts

unread,
Oct 21, 2007, 7:06:42 PM10/21/07
to
On 2007-10-19, Glenn Jackman <gle...@ncf.ca> wrote:
> Because you call interact without giving a key sequence to return
> control to the script, the interact command cannot return unless the
> interacting user ends the ssh session.

Ooops, my mistake in the new example. My original script was using "+"
to escape.

> If you want to be able to interact for a while, return control to the
> script, interact again, etc, there are factilities in expect to allow
> that.

[...]


> interact {
> ~x { return }
> -o eof { set ssh_open 0; return }
> }

A-ha! That's what I was missing. The "-o eof" allows me to trap the
spawn being closed. I've just incorporated this into my script and it
works beautifully.

Thank you very much for your assistance, Glenn.

Regards,
Ian.

0 new messages