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

This is a discussion on [expect] How to detect if process is closed from interact command - TCL ; 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 ...

+ Reply to Thread
Results 1 to 8 of 8

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

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

    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.

  2. Default Re: [expect] How to detect if process is closed from interact command

    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

  3. Default Re: [expect] How to detect if process is closed from interact command

    On 2007-10-17, Glenn Jackman <glennj@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.

  4. Default Re: [expect] How to detect if process is closed from interact command

    At 2007-10-17 07:22PM, "Ian Petts" wrote:
    > On 2007-10-17, Glenn Jackman <glennj@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.


    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?

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

  5. Default Re: [expect] How to detect if process is closed from interact command

    On 2007-10-18, Glenn Jackman <glennj@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)


  6. Default Re: [expect] How to detect if process is closed from interact command

    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
    "You can only be young once. But you can always be immature." -- Dave Barry

  7. Default Re: [expect] How to detect if process is closed from interact command

    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
    }

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

  8. Default Re: [expect] How to detect if process is closed from interact command

    On 2007-10-19, Glenn Jackman <glennj@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.

+ Reply to Thread

Similar Threads

  1. Possible expect bug: interact closes stdout
    By Application Development in forum TCL
    Replies: 0
    Last Post: 11-30-2007, 02:02 PM
  2. standalone process to interact with the web
    By Application Development in forum Python
    Replies: 11
    Last Post: 08-02-2007, 12:20 PM
  3. Re: expect - interact hangs
    By Application Development in forum TCL
    Replies: 0
    Last Post: 07-11-2007, 05:16 PM
  4. expect - interact hangs
    By Application Development in forum TCL
    Replies: 1
    Last Post: 07-11-2007, 12:11 PM
  5. Expect script hangs after interact call
    By Application Development in forum TCL
    Replies: 0
    Last Post: 07-03-2007, 06:22 PM