Expect a stdin redirect

I am running a script on a remote server, for example using this command:

ssh root@host 'bash -s' < script.sh

Now I am trying to use the wait command to process a password request. This is the script:

#!/usr/bin/expect
set cmd [lindex $argv 0]

spawn -noecho ssh root@host $cmd

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

If I ran the script, it did not return the result:

./ssh.exp 'bash -s' < script.sh

I know not to use ssh without a password, but here it is not a question.


UPDATE I tried the glenn jackman idea with a simple script, but it does not work. This is the script I use:

#!/usr/bin/expect
spawn ssh xxx@xxx

expect "*?assword:*"
send "pwd\r"

send "echo hello world"

This is the result I get:

[xxx@xxx bin]$ expect -d my.exp
expect version 5.43.0
argv[0] = expect  argv[1] = -d  argv[2] = my.exp
set argc 0
set argv0 "my.exp"
set argv ""
executing commands from command file my.exp
spawn ssh xxx@xxx
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {7599}

expect: does "" (spawn_id exp6) match glob pattern "*?assword:*"? no
xxx@xxx password:
expect: does "xxx@xxx password: " (spawn_id exp6) match glob pattern "*?assword:*"? yes
expect: set expect_out(0,string) "xxx@xxx password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "xxx@xxx password: "
send: sending "pwd" to { exp6 }
send: sending "echo hello world" to { exp6 }
write() failed to write anything - will sleep(1) and retry...


UPDATE I was able to run my script. This is the result that works:
#!/usr/bin/expect

set user [lindex $argv 0]
set host [lindex $argv 1]
set pwd  [lindex $argv 2]

spawn ssh $user@$host bash -s

expect {
  "?asswor?: " {
    send "$pwd\n"
  }
}

while {[gets stdin line] != -1} {
    send "$line\n"
}
send \004

expect {
  "END_TOKEN_OF_SCRIPT" {
    exit 0
  }
  default {
    exit 1
  }
}
+2
source share
2 answers

You need to send the script you are reading on stdin to the remote host:

while {[gets stdin line] != -1} {
    send "$line\r"
}

# then you may have to send ctrl-D to signal end of stdin
send \004
+5
source

expect_user, :

script , , . script , . (. stty, , - .)

send_user "password?\ "
expect_user -re "(.*)\n"
for {} 1 {} {
    if {[fork]!=0} {sleep 3600;continue}
    disconnect
    spawn priv_prog
    expect Password:
    send "$expect_out(1,string)\r"
    . . .
    exit
}

, :

#!/usr/local/bin/expect

# For debugging make the following to be line 1:
#!/usr/local/bin/expect -D 1

set timeout 20

send_user "Username?\ "
expect_user -re "(.*)\n"
set user $expect_out(1,string)

send_user "password?\ "
stty -echo
expect_user -re "(.*)\n"
stty echo
set password $expect_out(1,string)

spawn su

expect {

    "Password"  {send "$password\r"}

    "#"         {interact + return}

}
0

All Articles