简体   繁体   中英

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

I'm trying to use Expect in a Bash script to provide the SSH password. Providing the password works, but I don't end up in the SSH session as I should. It goes back strait to Bash.

My script:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com'
expect "password"
send "$PWD\n"
EOD
echo "you're out"

The output of my script:

spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
usr@$myhost.example.com's password: you're out

I would like to have my SSH session and, only when I exit it, to go back to my Bash script.

The reason why I am using Bash before Expect is because I have to use a menu. I can choose which unit/device to connect to.

To those who want to reply that I should use SSH keys, please abstain.

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.

The easiest way is to use sshpass . This is available in Ubuntu / Debian repositories and you don't have to deal with integrating expect with Bash.

An example:

sshpass -p<password> ssh <arguments>
sshpass -ptest1324 ssh user@192.168.1.200 ls -l /tmp

The above command can be easily integrated with a Bash script.

Note: Please read the Security Considerations section in man sshpass for a full understanding of the security implications.

Add the 'interact' Expect command just before your EOD:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
expect "password"
send "$PWD\n"
interact
EOD
echo "you're out"

This should let you interact with the remote machine until you log out. Then you'll be back in Bash.

After looking for an answer for the question for months, I finally find a really best solution: writing a simple script.

#!/usr/bin/expect

set timeout 20

set cmd [lrange $argv 1 end]
set password [lindex $argv 0]

eval spawn $cmd
expect "assword:"   # matches both 'Password' and 'password'
send "$password\r";
interact

Put it to /usr/bin/exp , then you can use:

  • exp <password> ssh <anything>
  • exp <password> scp <anysrc> <anydst>

Done!

A simple Expect script:

File Remotelogin.exp

    #!/usr/bin/expect
    set user [lindex $argv 1]
    set ip [lindex $argv 0]
    set password [lindex $argv 2]
    spawn ssh $user@$ip
    expect "password"
    send "$password\r"
    interact

Example:

./Remotelogin.exp <ip> <user name> <password>

Also make sure to use

send -- "$PWD\r"

instead, as passwords starting with a dash (-) will fail otherwise.

The above won't interpret a string starting with a dash as an option to the send command.

Use the helper tool fd0ssh (from hxtools, not pmt). It works without having to expect a particular prompt from the ssh program.

Another way that I found useful to use a small Expect script from a Bash script is as follows.

...
Bash script start
Bash commands
...
expect - <<EOF
spawn your-command-here
expect "some-pattern"
send "some-command"
...
...
EOF
...
More Bash commands
...

This works because ...If the string "-" is supplied as a filename, standard input is read instead...

sshpass is broken if you try to use it inside a Sublime Text build target, inside a Makefile. Instead of sshpass , you can use passh : https://github.com/clarkwang/passh

With sshpass you would do:

sshpass -p pa$$word ssh user@host

With passh you would do:

passh -p pa$$word ssh user@host

Note: Do not forget to use -o StrictHostKeyChecking=no . Otherwise, the connection will hang on the first time you use it. For example:

passh -p pa$$word ssh -o StrictHostKeyChecking=no user@host

References:

  1. Send command for password doesn't work using Expect script in SSH connection
  2. How can I disable strict host key checking in ssh?
  3. How to disable SSH host key checking
  4. scp without known_hosts check
  5. pam_mount and sshfs with password authentication

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM