Reputation: 3160
I'm running a script on a remote server like using this command:
ssh root@host 'bash -s' < script.sh
Now I'm trying to use expect to handle the password prompt. 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 run the script, it gives no output:
./ssh.exp 'bash -s' < script.sh
I know that's not the way to use ssh without password, but this is not the question right here.
UPDATE I tried the idea of glenn jackman with a simple script but it's not working. This is the script I'm using:
#!/usr/bin/expect
spawn ssh xxx@xxx
expect "*?assword:*"
send "pwd\r"
send "echo hello world"
This is the output 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's password:
expect: does "xxx@xxx's password: " (spawn_id exp6) match glob pattern "*?assword:*"? yes
expect: set expect_out(0,string) "xxx@xxx's password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "xxx@xxx's password: "
send: sending "pwd" to { exp6 }
send: sending "echo hello world" to { exp6 }
write() failed to write anything - will sleep(1) and retry...
#!/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
}
}
Upvotes: 3
Views: 10697
Reputation: 1
Use expect_user, as shown in the man page:
The following script reads a password, and then runs a program every hour that demands a password each time it is run. The script supplies the password so that you only have to type it once. (See the stty command which demonstrates how to turn off password echoing.)
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
}
Here is what I currently have, still improving it though:
#!/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}
}
Upvotes: 0
Reputation: 246774
You need to send the script you read 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
Upvotes: 7