282

I need to create a script that automatically inputs a password to OpenSSH ssh client.

Let's say I need to SSH into myname@somehost with the password a1234b.

I've already tried...

#~/bin/myssh.sh
ssh myname@somehost
a1234b

...but this does not work.

How can I get this functionality into a script?

0

25 Answers 25

354

First you need to install sshpass.

  • Ubuntu/Debian: apt-get install sshpass
  • Fedora/CentOS: yum install sshpass
  • Arch: pacman -S sshpass

Example:

sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM

Custom port example:

sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM:2400

Notes:

  • sshpass can also read a password from a file when the -f flag is passed.
    • Using -f prevents the password from being visible if the ps command is executed.
    • The file that the password is stored in should have secure permissions.
Sign up to request clarification or add additional context in comments.

16 Comments

just be aware that while sshpass blocks your password from commands like ps -aux, you shouldn't normally run commands by typing your password because other users on the same computer may be able to see the password by running ps -aux. if practical, you also want to use public key authentication instead, as mentioned in the other answer. this allows you to separate authentication info from your script so you can share your script with others worry-free, and later decide to enable encryption on your ~/.ssh folder without also encrypting your script.
Unfortunately this isn't working for me on a server with a custom ssh port...why can't ssh just give us the option to insert the password in the command line?
for custom port to work add "-p port-number" at the end of command
sshpass has an option, -f, to read the password from a file. Thus, it won't be visible when using ps, and if the file has appropriate permissions in one's own home directory, it should be safe.
|
188

After looking for an answer to the question for months, I finally found a better 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, So you can use:

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

Done!

10 Comments

This answer should get more votes imo, it is a great wrapper. Just tried a few common operations like rsyncing with various flags and remote command execution and it worked every time. Added to my toolbox of useful scripts, Thanks @damn_c!
The reason why this is IMO not a very good answer is because the password is written in the script which is by far the least secure method...
@PierreE the password is specified on the command line, not in the script.
The password will be visible by anyone who runs ps on the machine.
i've added log_user 0 to skip some unrequired logs
|
84

Use public key authentication: https://help.ubuntu.com/community/SSH/OpenSSH/Keys

In the source host run this only once:

ssh-keygen -t rsa # ENTER to every field
ssh-copy-id myname@somehost

That's all, after that you'll be able to do ssh without password.

12 Comments

I see. But I am REQUIRED to ssh with password. This is because, "I" may have the script on a thumb drive and need to run it from any computer; while not disabling the need for password.
@user1467855, I think you need to better explain your requirements. Nobody is suggesting that you have an unsecure network. In the public-key approach, it would still be possible for users to log in with the password. But you would copy the private key onto your thumb drive, which means the thumb drive would be the only thing that can log in without a password.
Unfortunately, I am in OP situation, because the sysadmin disallows authentication by rsa/dsa keys and requires passwors. What are you gonna do.
Downvoted because this doesn't even try to answer the actual question asked.
This still prompts for the first login and cannot be used in a script!
|
33

You could use an expects script. I have not written one in quite some time but it should look like below. You will need to head the script with #!/usr/bin/expect

#!/usr/bin/expect -f
spawn ssh HOSTNAME
expect "login:" 
send "username\r"
expect "Password:"
send "password\r"
interact

7 Comments

I did as you suggested but get the following errors: /bin/myssh.sh: 2: spawn: not found /bin/myssh.sh: 3: expect: not found /bin/myssh.sh: 4: send: not found /bin/myssh.sh: 5: expect: not found /bin/myssh.sh: 6: send: not found
Thanks Aaron for modifying my answer to be correct. You may need to run the below command to find the correct path to put in for expect.which expect
You can also use this shebang line: #!/usr/bin/env expect
I added interact to the end so the ssh session is actually interactive
@AaronDigulla, how is this any less secure than any alternatives, for example the private key is also readable? Perhaps we should suggest that the script be readable only by the user?
|
26

Variant I

sshpass -p PASSWORD ssh USER@SERVER

Variant II

#!/usr/bin/expect -f
spawn ssh USERNAME@SERVER "touch /home/user/ssh_example"
expect "assword:"
send "PASSWORD\r"
interact

4 Comments

No. sshpass is not ssh. SYNOPSIS sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments
In order to run sshpass in Linux CentOS you must yum -y install epel-release and then yum -y install sshpass
In this context of this data can be ignored
While I know this is an old post it's worth noting that the Variant II method would leave the password given to the session vulnerable in the bash history, making it highly inadvisable.
16

sshpass + autossh

One nice bonus of the already-mentioned sshpass is that you can use it with autossh, eliminating even more of the interactive inefficiency.

sshpass -p mypassword autossh -M0 -t [email protected]

This will allow autoreconnect if, e.g. your wifi is interrupted by closing your laptop.

With a jump host

sshpass -p `cat ~/.sshpass` autossh -M0 -Y -tt -J [email protected]:22223 -p 222 [email protected]

3 Comments

Note that you can't add option -f to autossh in this combination, because when used with autossh, ssh will be *unable* to ask for passwords or passphrases. harding.motd.ca/autossh/README.txt also superuser.com/questions/1278583/…
This seems to work at first, but since the -M0 flag disables monitoring my connection fails after a while without autossh realizing it; if I omit the flag then it also works until the connection fails, at which point my password is rejected by the server
Note that with this solution, anyone who logs into your system can see the password using ps -ef or some such command.
15

sshpass with better security

I stumbled on this thread while looking for a way to ssh into a bogged-down server -- it took over a minute to process the SSH connection attempt, and timed out before I could enter a password. In this case, I wanted to be able to supply my password immediately when the prompt was available.

(And if it's not painfully clear: with a server in this state, it's far too late to set up a public key login.)

sshpass to the rescue. However, there are better ways to go about this than sshpass -p.

My implementation skips directly to the interactive password prompt (no time wasted seeing if public key exchange can happen), and never reveals the password as plain text.

#!/bin/sh
# preempt-ssh.sh
# usage: same arguments that you'd pass to ssh normally
echo "You're going to run (with our additions) ssh $@"

# Read password interactively and save it to the environment
read -s -p "Password to use: " SSHPASS 
export SSHPASS

# have sshpass load the password from the environment, and skip public key auth
# all other args come directly from the input
sshpass -e ssh -o PreferredAuthentications=keyboard-interactive -o PubkeyAuthentication=no "$@"

# clear the exported variable containing the password
unset SSHPASS

5 Comments

note to self: update script to use trap to prevent ctrl-C from leaking the SSHPASS variable
I found that PreferredAuthentications=keyboard-interactive didn't work, but replacing it with PreferredAuthentications=password worked.
I'm running ssh inside the remote machine again, with the same password. Right now I'm exporting SSHPASS into the remote machine with export SSHPASS=$SSHPASS. Is there a safer way? To provide some context, I ssh into a cluster of machines, set up ssh keys, and then distribute them into other computers in the cluster. All of that runs from a script in a single computer. So I need 2 levels of ssh.
This solution is only for the case where you don't have prior access to the machine to set up a key-based login. I would look at key forwarding dev.to/levivm/…
Storing the secret as environment variable is no way "better security". It is worse.
10

I don't think I saw anyone suggest this and the OP just said "script" so...

I needed to solve the same problem and my most comfortable language is Python.

I used the paramiko library. Furthermore, I also needed to issue commands for which I would need escalated permissions using sudo. It turns out sudo can accept its password via stdin via the "-S" flag! See below:

import paramiko

ssh_client = paramiko.SSHClient()

# To avoid an "unknown hosts" error. Solve this differently if you must...
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# This mechanism uses a private key.
pkey = paramiko.RSAKey.from_private_key_file(PKEY_PATH)

# This mechanism uses a password.
# Get it from cli args or a file or hard code it, whatever works best for you
password = "password"

ssh_client.connect(hostname="my.host.name.com",
                       username="username",
                       # Uncomment one of the following...
                       # password=password
                       # pkey=pkey
                       )

# do something restricted
# If you don't need escalated permissions, omit everything before "mkdir"
command = "echo {} | sudo -S mkdir /var/log/test_dir 2>/dev/null".format(password)

# In order to inspect the exit code
# you need go under paramiko's hood a bit
# rather than just using "ssh_client.exec_command()"
chan = ssh_client.get_transport().open_session()
chan.exec_command(command)

exit_status = chan.recv_exit_status()

if exit_status != 0:
    stderr = chan.recv_stderr(5000)

# Note that sudo's "-S" flag will send the password prompt to stderr
# so you will see that string here too, as well as the actual error.
# It was because of this behavior that we needed access to the exit code
# to assert success.

    logger.error("Uh oh")
    logger.error(stderr)
else:
    logger.info("Successful!")

Hope this helps someone. My use case was creating directories, sending and untarring files and starting programs on ~300 servers as a time. As such, automation was paramount. I tried sshpass, expect, and then came up with this.

Comments

9
# create a file that echo's out your password .. you may need to get crazy with escape chars or for extra credit put ASCII in your password...
echo "echo YerPasswordhere" > /tmp/1
chmod 777 /tmp/1

# sets some vars for ssh to play nice with something to do with GUI but here we are using it to pass creds.
export SSH_ASKPASS="/tmp/1"
export DISPLAY=YOURDOINGITWRONG
setsid ssh [email protected] -p 22

reference: https://www.linkedin.com/pulse/youre-doing-wrong-ssh-plain-text-credentials-robert-mccurdy?trk=mp-reader-card

4 Comments

I think this article is just being sarcastic!
sarcastic maybe? but this fine if trying to automate against systems with their default admin if you are in the process of provisioning them
No this does not require 'expect' or 'sshpass' ... this being one of the ONLY ways to ssh with just native Debian install ... so this works without root @nhed Also note 90% of these are just using non native programing, expect or sshpass all being the same 'answer' mine is the best ... so there ;P
I agree that it does not require expect / sshpass. @RmccurdyDOTcom didn't notice you linked your pwn article, so yeah you would know if you were sarcastic or not - but on that front I was referring to the prior comment by Yan. Personally I would try to abstain from clear text and opt for ssh keys but there is the issue of bootstrapping virgin systems - where i think this is a good option if seeding the right public keys is not an option.
8

This is how I login to my servers.

ssp <server_ip>
  • alias ssp='/home/myuser/Documents/ssh_script.sh'
  • cat /home/myuser/Documents/ssh_script.sh
#!/bin/bash
sshpass -p mypassword ssh root@$1

And therefore...

ssp server_ip

2 Comments

It seems all of your servers have same password
and the password is written in clear text in a script. Unsecure.
5

This is basically an extension of abbotto's answer, with some additional steps (aimed at beginners) to make starting up your server, from your linux host, very easy:

  1. Write a simple bash script, e.g.:
#!/bin/bash

sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no <YOUR_USERNAME>@<SEVER_IP>
  1. Save the file, e.g. 'startMyServer', then make the file executable by running this in your terminal:
sudo chmod +x startMyServer
  1. Move the file to a folder which is in your 'PATH' variable (run 'echo $PATH' in your terminal to see those folders). So for example move it to '/usr/bin/'.

And voila, now you are able to get into your server by typing 'startMyServer' into your terminal.

P.S. (1) this is not very secure, look into ssh keys for better security.

P.S. (2) SMshrimant answer is quite similar and might be more elegant to some. But I personally prefer to work in bash scripts.

Comments

5

I am using below solution but for that you have to install sshpass If its not already installed, install it using sudo apt install sshpass

Now you can do this,

sshpass -p *YourPassword* ssh root@IP

You can create a bash alias as well so that you don't have to run the whole command again and again. Follow below steps

cd ~

sudo nano .bash_profile

at the end of the file add below code

mymachine() { sshpass -p *YourPassword* ssh root@IP }

source .bash_profile

Now just run mymachine command from terminal and you'll enter your machine without password prompt.

Note:

  1. mymachine can be any command of your choice.
  2. If security doesn't matter for you here in this task and you just want to automate the work you can use this method.

3 Comments

Note that .bash_profile is quite often word-readable. So putting your password there is not a good idea.
Thank you @MartinPrikryl for addressing the issue, I have updated the note at the end so anyone who is using this solution, is also aware that password is easily readable.
Should not need sudo to edit your own .bash_profile... :/
3

If you are doing this on a Windows system, you can use Plink (part of PuTTY).

plink your_username@yourhost -pw your_password

2 Comments

For automatic script, don't forget the option "-no-antispoof" or the console will waiting with a message "Access granted. Press Return to begin session.". The command to be executed should be placed at the end: plink your_username@yourhost -pw your_password -no-antispoof your_command
PuTTY have GUI options to store password, do not need cli anymore
1

This works:

#!/usr/bin/expect -f
spawn ssh USERNAME@SERVER "touch /home/user/ssh_example"
expect "assword:"
send "PASSWORD\r"
interact

BUT!!! If you have an error like below, just start your script with expect, but not bash, as shown here: expect myssh.sh instead of bash myssh.sh

/bin/myssh.sh: 2: spawn: not found /bin/myssh.sh: 3: expect: not found /bin/myssh.sh: 4: send: not found /bin/myssh.sh: 5: expect: not found /bin/myssh.sh: 6: send: not found

Comments

0

I have a better solution that inclueds login with your account than changing to root user. It is a bash script

http://felipeferreira.net/index.php/2011/09/ssh-automatic-login/

1 Comment

The link is broken
0

The answer of @abbotto did not work for me, had to do some things differently:

  1. yum install sshpass changed to - rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/sshpass-1.05-1.el6.x86_64.rpm
  2. the command to use sshpass changed to - sshpass -p "pass" ssh user@mysite -p 2122

Comments

0

I got this working as follows

.ssh/config was modified to eliminate the yes/no prompt - I'm behind a firewall so I'm not worried about spoofed ssh keys

host *
     StrictHostKeyChecking no

Create a response file for expect i.e. answer.expect

set timeout 20
set node [lindex $argv 0]
spawn ssh root@node service hadoop-hdfs-datanode restart

expect  "*?assword {
      send "password\r"   <- your password here.

interact

Create your bash script and just call expect in the file

#!/bin/bash
i=1
while [$i -lt 129]    # a few nodes here
  
  expect answer.expect hadoopslave$i

  i=[$i + 1]
  sleep 5

done

Gets 128 hadoop datanodes refreshed with new config - assuming you are using a NFS mount for the hadoop/conf files

Hope this helps someone - I'm a Windows numpty and this took me about 5 hours to figure out!

1 Comment

"I'm behind a firewall so I'm not worried about spoofed ssh keys". A firewall does exactly nothing in this case. The HostKeyCheck is so you can verify the host on the other end is not a trojan Host. I.e. one that's just pretending to be where you want to connect to. If you connect to an unknown host, and do something sensitive, like write a file that has credentials or a token or enter a password, that information is now effectively public knowledge. You being behind a firewall is irrelevant.
0

Solution1:use sshpass

#~/bin/myssh.sh
sshpass -p a1234b ssh myname@somehost

You can install by

# Ubuntu/Debian
$ sudo apt-get install sshpass

# Red Hat/Fedora/CentOS
$ sudo yum install sshpass

# Arch Linux
$ sudo pacman -S sshpass

#OS X
brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb

or download the Source Code from here, then

tar xvzf sshpass-1.08.tar.gz 
cd sshpass-1.08.tar.gz 
./configure
sudo make install

Solution2:Set SSH passwordless login

Let's say you need to SSH into [email protected](Remote server B) with the password 2b2b2b from [email protected](Client server A).

Generate the public key(.ssh/id_rsa.pub) and private key(.ssh/id_rsa) in A with the following commands

ssh-keygen -t rsa
[Press enter key]
[Press enter key]
[Press enter key]

Use the following command to distribute the generated public key(.ssh/id_rsa.pub) to server B under bbb‘s .ssh directory as a file name authorized_keys

ssh-copy-id [email protected]

You need to enter a password for the first ssh login, and it will be logged in automatically in the future, no need to enter it again!

ssh [email protected] [Enter]
2b2b2b

And then your script can be

#~/bin/myssh.sh
ssh myname@somehost

Comments

-1

I managed to get it working with that:

SSH_ASKPASS="echo \"my-pass-here\""
ssh -tt remotehost -l myusername

Comments

-1

In the example bellow I'll write the solution that I used:

The scenario: I want to copy file from a server using sh script:

#!/usr/bin/expect
$PASSWORD=password
my_script=$(expect -c "spawn scp userName@server-name:path/file.txt /home/Amine/Bureau/trash/test/
expect \"password:\"
send \"$PASSWORD\r\"
expect \"#\"
send \"exit \r\"
")

echo "$my_script"

Comments

-2

What i did here is

  1. ssh-keygen - generate ssh key
  2. copy the public key to the remote server. You can use ssh-copy-id or you can do it manually like this cat ~/.ssh/id_rsa.pub | ssh root@ip 'cat >> ~/.ssh/authorized_keys'
  3. Test it ssh root@ip

After that I add it on my .zshrc for easy use

sy-login(){
    ssh root@ip
} 

References

https://www.ssh.com/academy/ssh/copy-id

https://www.makeuseof.com/tag/beginners-guide-setting-ssh-linux-testing-setup/

1 Comment

This is what at least two existing answers how already (and technically, it's not an answer to the question, at least not without some explanation).
-3

Use this script tossh within script, First argument is the hostname and second will be the password.

#!/usr/bin/expect
set pass [lindex $argv 1]
set host [lindex $argv 0]
spawn ssh -t root@$host echo Hello
expect "*assword: " 
send "$pass\n";
interact"

2 Comments

What does this show on top of the existing answers? Particularly those by damn_c, Lipongo or RemiZOffAlex and others...
script execution along with ssh #!/usr/bin/expect set pass [lindex $argv 1] set host [lindex $argv 0] spawn ssh -t root@$host sh /tmp/anyscript.sh expect "*assword: " send "$pass\n"; interact"
-4

To connect remote machine through shell scripts , use below command:

sshpass -p PASSWORD ssh -o StrictHostKeyChecking=no USERNAME@IPADDRESS

where IPADDRESS, USERNAME and PASSWORD are input values which need to provide in script, or if we want to provide in runtime use "read" command.

1 Comment

What does this answer show on top of existing answers? + Never ever suggest anyone to use StrictHostKeyChecking=no without explaining the consequences.
-4

This should help in most of the cases (you need to install sshpass first!):

#!/usr/bin/bash
read -p 'Enter Your Username: ' UserName;
read -p 'Enter Your Password: ' Password;
read -p 'Enter Your Domain Name: ' Domain;

sshpass -p "$Password" ssh -o StrictHostKeyChecking=no $UserName@$Domain

2 Comments

What does this show what other existing answers don't already? + Never suggest anyone to use StrictHostKeyChecking=no without explaining the security consequences.
I do not see any "quick and dirty" in the OP.
-22

In linux/ubuntu

ssh username@server_ip_address -p port_number

Press enter and then enter your server password

if you are not a root user then add sudo in starting of command

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.