9

There are several posts regarding the same, but i still not able to make my expect script work properly. My intention is to automate everything but leave the password enter for the user. So there are 3 parts of the script:

  1. automated login
  2. give the user interaction to enter the password
  3. give control back to Expect script to continue work

So i have script which will be spawned and which have 3 read commands. First and last should be filled by Expect and second one i would like to enter my self:

#!/bin/ksh
read user?User:
echo "Expect entered the username $user"
read pass?Password:
echo "User entered the password $pass"
read command?"Shell>"
echo "Expect entered the command $command"

My expect script:

#!/usr/bin/expect
spawn ./some_script
expect User
send I-am-expect\r
expect Password
interact
expect Shell
send I-am-expect-again

Unfortunately after i have entered the password the script does not continue and left in the interact mode:

[root@localhost ~]# ./my-expect
spawn ./some_script
User:I-am-expect
Expect entered the username I-am-expect
Password:i am user
User entered the password i am user
Shell>

And finally when i entering something on the "Shell" and pressing [ENTER] expect exits with the error:

Expect entered the command
expect: spawn id exp4 not open
    while executing
"expect Shell"
    (file "./my-expect" line 7)
[root@localhost ~]#

I appriciate any explanation or resolution of this issue. I am using expect version 5.45

ks1322
  • 33,961
  • 14
  • 109
  • 164
Petras L
  • 183
  • 1
  • 1
  • 7

2 Answers2

4

You can read (expect_user) the user's password by yourself and then send it to the spawn'ed program. For example:

[STEP 101] # cat foo.exp
proc expect_prompt {} \
{
    global spawn_id
    expect -re {bash-[.0-9]+(#|\$)}
}

spawn ssh -t 127.0.0.1 bash --noprofile --norc
expect "password: "

stty -echo
expect_user -timeout 3600 -re "(.*)\[\r\n]"
stty echo
send "$expect_out(1,string)\r"

expect_prompt
send "exit\r"
expect eof
[STEP 102] # expect foo.exp
spawn ssh -t 127.0.0.1 bash --noprofile --norc
root@127.0.0.1's password:
bash-4.3# exit
exit
Connection to 127.0.0.1 closed.
[STEP 103] #
pynexj
  • 19,215
  • 5
  • 38
  • 56
  • I notices what seems to be an "escape" for one square bracket but not the other. Is that intentional? (half way down) `\[\r\n]"` – Ari Feb 06 '19 at 11:30
  • The open bracket is special (https://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M11) but the close bracket is not. There would be no harm to escape the close bracket, but it is not strictly necessary. – glenn jackman Feb 07 '19 at 15:03
2

The interact should be given with proper condition for the exit criteria.

The following script will execute the user commands in the shell

exeCmds.sh

#!/bin/bash
read -p "User: " user
echo "Expect entered the username $user"
read -p "Password: " pass
echo "User entered the password $pass"
while :
do
        # Simply executing the user inputs in the shell
        read -p "Shell> " command
        $command
done

automateCmdsExec.exp

#!/usr/bin/expect 
spawn ./exeCmds.sh
expect User
send dinesh\r
expect Password
send welcome!2E\r
expect Shell>
puts "\nUser can interact now..."
puts -nonewline "Type 'proceed' for the script to take over\nShell> "
while 1 {
        interact "proceed" {puts "User interaction completed.";break}
}
puts "Script take over the control now.."

# Now, sending 'whoami' command from script to shell
send "whoami\r"
expect Shell>

# Your further code here...

The script automateCmdsExec.exp will address the login needs of the bash script and when the prompt arrives, it will hand over the control to user.

We should define an exit criteria for the interact for which I have used the word proceed. (You can alter it as per your need).

Once interact matched the word proceed. it will return the control back to the expect script.

For demo purpose, I kept one more send-expect pair of command.

i.e.

send "whoami\r"
expect Shell>

You can keep your further code below the interact, thus it can be executed by script.

Dinesh
  • 16,014
  • 23
  • 80
  • 122
  • 3
    Yes, but i would like to give control to expect right after the password is entered. Immediately after the Enter key is pressed. In original scenario i do not have posibility to enter something like "proceed" or "go" to pass control back to expect. Script i have provided is just an example/simulator of shell i am trying to communicate to. The main idea is to let the user enter just a password and expect will do the rest. I do not want to hardcode password in the script or pass it through arguments. – Petras L Nov 23 '15 at 15:29
  • @PetrasL I have a similar need. Did you finally figure out a soution? – Stéphane Gourichon May 06 '20 at 16:08
  • @PetrasL It can be highly appreciated if you can conclude your question, either by updating your question or by adding comment on the answer which you accepted, since the answers provided here do not precisely answer your question. – Abdul Salam Jul 29 '20 at 13:37