By Max


2011-01-24 10:22:45 8 Comments

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 [email protected]$myhost.example.com'
expect "password"
send "$PWD\n"
EOD
echo "you're out"

The output of my script:

spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no [email protected]$myhost.example.com
[email protected]$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.

9 comments

@user 2019-04-28 08:37:12

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 [email protected]

With passh you would do:

passh -p pa$$word ssh [email protected]

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 [email protected]

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

@Vijay S B 2016-09-23 05:23:30

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 [email protected]$ip
    expect "password"
    send "$password\r"
    interact

Example:

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

@Jimbo 2014-12-30 09:13:04

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...

@Tino 2018-06-12 18:29:56

You do not need the - here, as expect reads from stdin by default if you invoke it without argument. However it is useful if you want to run it interactively without command prompt (expect vs. expect -) or in case you do something like expect -f "[email protected]" where the first argument shall be a file, even if it looks like an option (starts with -). In that case, if $1 (the file given) is - this reads from stdin.

@Timmah 2014-01-22 10:32:09

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.

@dotnix 2013-07-08 18:45:45

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 [email protected] 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.

@erikbwork 2015-02-10 18:52:39

I don't know if it's a good solution, but it certainly simplifies a lot. Thanks

@Charles Duffy 2015-05-21 22:45:11

Very dangerous from a security perspective -- command-line arguments can be read by any other process on the system. It's possible to overwrite them, and hopefully sshpass does that, but even then there's a period while it's still starting up before it's able to do that when the password is available for any/every process to see.

@dotnix 2015-05-22 17:16:32

@CharlesDuffy Of course, you are correct. sshpass is used in a scenario where you have simple test scripts that execute in a local network environment where security is not the top concern. In fact, there is a section in man sshpass where a whole section on Security Considerations is explained. Added this to answer, Thanks.

@m3nda 2015-06-05 19:36:08

@erikb85 Usually, a package does all the dirty stuff for you, but, in all cases, these scripts are built just for that usage, then would be BETTER than add your own stuff. This comment is about don't reinvent the wheel. Deal with hard stuff only if no people has dealed yet with it. sshpass it's a good function.

@erikbwork 2015-07-01 11:46:39

@erm3nda Your comment applies to use OpenSSL instead of implenting your own SSL library. It might be nasty in the details so let experts deal with it. But sshpass is not just a very small tool, it's doing something inherently wrong. You should not do it this way. Use RSA key files instead if you don't want to use passwords. It's not about the nasty details, but about it's inherent problem of writing clear text passwords in a line of bash. Avoid such tools! (Of course I'm also use it because I'm lazy, but you really shouldn't actually)

@m3nda 2015-07-01 15:40:12

@erikb85 I actually use keys the the most ssh connections i made, but sshpass has make the work instead of have to manually enter that data. There are so many scenarios.

@Ron Burk 2016-04-14 16:27:30

For completeness, I mention that "man sshpass" delivers suitable security warnings to the prospective user, points out that "-p" is the least secure way to use it, and offers the "-e" option for taking the password via environment variable, which at least keeps it off the command line.

@dr-jan 2011-01-24 19:04:39

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

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no [email protected]$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.

@Emmanuel 2013-04-30 14:03:29

It goes in and goes back out immediately. "you're out" is printed.

@Emmanuel 2013-04-30 14:08:30

I've replaced "interact" and "EOD" with "expect eof" and it worked for me. This is on a Mac.

@moertel 2017-10-09 12:21:46

None of the answers on this page worked for me but @Emmanuel's suggestion to use expect eof solved the issue.

@Tino 2018-06-12 18:32:49

Remove the ' from [email protected]$myhost.example.com' and it should work. And perhaps you need to replace \n with \r, but YMMV

@user562374 2011-01-24 11:55:06

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

@JP Illanes 2011-11-02 23:54:20

This is great! It's a bit hard to make it run (at least in ubuntu server) but works smoothly! The config we made: echo "yoursshpass" | fd0ssh ssh -c -L$port:$ip:$remote_port [email protected] & THANKS!

@Charles Duffy 2015-05-21 22:46:27

Much safer than passing the password on the command line as sshpass does.

@Piotr Król 2011-01-24 14:32:57

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 [email protected]$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 [email protected]$myhost.example.com; interact }'

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

@Max 2011-01-25 13:28:32

it works great, thanks. What if I want to type in command once I'm logged in via SSH, what do I need to do?

@Piotr Król 2011-01-25 13:49:13

This script should return ineractive shell with logged in user. I dont understand question. If you absolutely want to use the same script in bash look at the edited entry.

@Max 2011-01-26 14:43:28

The same way I send the password when prompted, I would like to send system commands once logged in.

@Piotr Król 2011-01-26 15:37:53

Samlple code was added to post above. Of course this will work until my_commandX don't change returned prompt, if this happens prompt variable should be changed.

@Richard 2012-09-20 11:12:13

@pietrushnic can you explain a bit why use "interact -o -nobuffer -re $prompt return", instead of "expect $prompt"? the latter one looks more commonly used..

@Piotr Król 2012-09-27 10:09:58

@Richard best explanation was provided on wiki.tcl.tk/3914, "The major difference is that interact sets up a background matching event loop. expect blocks foreground processing (and ignores user input) during it's matching event loop. interact also has a set of switches that allow programmers to spawn two sessions and connect their ptys, thus letting them drive each other."

@Piotr Król 2015-12-23 13:33:33

@Abdull mainly because solution is cleaner and more readable. Using expect from bash does not add anything to solution. Also I meant more code sample provided in question and the way it mix expect and bash, then general rule of not mixing those two scripting languages.

@pynexj 2018-04-23 15:49:00

take a look at sexpect. you can write expect scripts with bash only.

@damn_c 2015-02-03 07:12:14

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 "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!

@user 2019-04-28 07:45:50

expect "assword:" did you meant expect "password:"?

@Ferdinand.kraft 2019-06-04 00:36:28

@user "assword" will match both Password and password.

Related Questions

Sponsored Content

38 Answered Questions

[SOLVED] How can I check if a program exists from a Bash script?

  • 2009-02-26 21:52:49
  • gregh
  • 735718 View
  • 2319 Score
  • 38 Answer
  • Tags:   bash

8 Answered Questions

[SOLVED] What does set -e mean in a bash script?

  • 2013-10-27 19:06:32
  • AndreaNobili
  • 422054 View
  • 772 Score
  • 8 Answer
  • Tags:   linux bash shell sh

29 Answered Questions

[SOLVED] Pipe to/from the clipboard in Bash script

11 Answered Questions

[SOLVED] Check existence of input argument in a Bash shell script

  • 2011-06-26 05:49:21
  • user775187
  • 1322911 View
  • 1432 Score
  • 11 Answer
  • Tags:   bash shell

14 Answered Questions

[SOLVED] How do I set a variable to the output of a command in Bash?

35 Answered Questions

[SOLVED] How can I check if a directory exists in a Bash shell script?

  • 2008-09-12 20:06:25
  • Grundlefleck
  • 2847511 View
  • 3816 Score
  • 35 Answer
  • Tags:   bash shell unix posix

29 Answered Questions

[SOLVED] How to specify the private SSH-key to use when executing shell command on Git?

  • 2010-12-30 19:42:01
  • Christoffer
  • 1161723 View
  • 1211 Score
  • 29 Answer
  • Tags:   git bash shell ssh

37 Answered Questions

[SOLVED] How do I parse command line arguments in Bash?

17 Answered Questions

[SOLVED] How to use SSH to run a local shell script on a remote machine?

67 Answered Questions

[SOLVED] How to get the source directory of a Bash script from within the script itself?

  • 2008-09-12 20:39:56
  • Jiaaro
  • 1807258 View
  • 5129 Score
  • 67 Answer
  • Tags:   bash directory

Sponsored Content