How to Use a Linux Expect Script to Enter Answer a Prompt for Password

How to use a linux expect script to enter answer a prompt for password

From the comment I got from glenn jackman I was able to figure out that the password prompt was not being matched. I changed my first line to #!/var/bin/expect -d which provided the necessary debugging output to find out the problem and fix it.

Thanks Glenn!

Hitting a return at password prompt in expect script instead of sending password

In a here-doc, variables like $Username and $Password are being expanded by the shell, so they're not seen as literals for Expect to expand. Since those shell variables aren't set anywhere, they're being expanded to null strings. As a result, it's executing ssh @$FQDN and sending an empty password.

You need to escape the $ so that Expect can process them.

You also don't need the set FQDN line in the Expect script, since you're using the shell variable for that.

#!/usr/bin/bash
FQDN=$1
LogFile=/tmp/Router_${FQDN}.txt
> $LogFile
expect -d <<EOF > $LogFile
set timeout 20
set Username "user"
set Password "***$$$"
spawn ssh \$Username@$FQDN
expect "*assword:"
send "\$Password\r"
expect "#"
send "some command\r"
expect "#"
send "exit\r"
sleep 1
exit
expect eof
EOF
cat $LogFile

Or you could set them as shell variables, just like FQDN.

#!/usr/bin/bash
FQDN=$1
Username=user
Password="***$$$"
LogFile=/tmp/Router_${FQDN}.txt
> $LogFile
expect -d <<EOF > $LogFile
set timeout 20
spawn ssh $Username@$FQDN
expect "*assword:"
send "$Password\r"
expect "#"
send "some command\r"
expect "#"
send "exit\r"
sleep 1
exit
expect eof
EOF
cat $LogFile

How can I make an expect script prompt for a password?

Use expect's stty command like this:

# grab the password
stty -echo
send_user -- "Password for $user@$host: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set pass $expect_out(1,string)

#... later
send -- "$pass\r"

Note that it's important to call stty -echo before calling send_user -- I'm not sure exactly why: I think it's a timing issue.

expect programmers should all read the book: Exploring Expect by Don Libes

Enter sudo password while in expect script

The answer from Donal Fellows is the right way to go, but for completeness here is the interact solution you were trying for. The command to use is

expect {
"Input 1" { send -- "$env(input1)\r"; exp_continue }
"Input 2" { send -- "$env(input2)\r"; exp_continue }
"password for" { stty -echo
interact -u tty_spawn_id -o "\r" return
stty echo
exp_continue }
eof
}

The problem you have is that you are running expect with the script on stdin, so interact has trouble unless you use -u tty_spawn_id to get it to work with /dev/tty and the user. You need to set the echo on/off on this tty explicitly, as sudo will only have done it on the pty between the spawned command and expect.

Expect Script - Auto Password

This is the part you're having trouble with:

spawn ssh "root@$ip mkdir -p .ssh"
expect "password:"
send "root\r"
expect "(yes/no)? "
send "yes\r"

After you send the password you're waiting 30 seconds for (yes/no? to appear, but it might not appear if you've connected to that machine before. You want to conditionally expect that y/n prompt:

spawn ssh "root@$ip mkdir -p .ssh"
expect {
"(yes/no)? " { send "yes\r"; exp_continue }
"password:" { send "root\r" }
}
expect eof

That form of the expect command allows you to look for multiple strings simultaneously. If the first one seen is "(yes/no)? ", then send "yes" and continue with this expect command. When you see "password:", send the password and let the expect command end.

You might want to change the second spawn command
so a shell can handle the pipeline.

set cmd [format {cat "~/.ssh/id_rsa.pub" | ssh "root@%s" 'cat >> .ssh/authorized_keys'} $ip]
spawn sh -c $cmd

Use Expect in a Bash script to provide a password to an SSH command

Mixing Bash and Expect is not a good way to achieve the desired effect. I'd try to use only Expect:

#!/usr/bin/expect
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com

# Use the correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "my_password\r"
interact -o -nobuffer -re $prompt return
send "my_command1\r"
interact -o -nobuffer -re $prompt return
send "my_command2\r"
interact

Sample solution for bash could be:

#!/bin/bash
/usr/bin/expect -c 'expect "\n" { eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com; interact }'

This will wait for Enter and then return to (for a moment) the interactive session.



Related Topics



Leave a reply



Submit