Automatically enter SSH password with script
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
24 Answers 24
First you need to install sshpass.
- Ubuntu/Debian: apt-get install sshpass
- Fedora/CentOS: yum install sshpass
- Arch: pacman -S sshpass
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
- 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.
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?
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:
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.
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.
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.
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
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
@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?
sshpass -p PASSWORD ssh USER@SERVER
#!/usr/bin/expect -f spawn ssh USERNAME@SERVER "touch /home/user/ssh_example" expect "assword:" send "PASSWORD\r" interact
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
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.
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
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/…
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 myusername@myserver.mydomain.com
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 me@jumphost.mydomain.com:22223 -p 222 me@server.mydomain.com
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.
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.
How to provide password to a command that prompts for one in bash?
I’m writing a UNIX shell function that is going to execute a command that will prompt the user for a password. I want to hard-code the password into the script and provide it to the command. I’ve tried piping the password into the command like this:
This may not work for some commands as the command may flush the input buffer before prompting for the password. I’ve also tried redirecting standard input to a file containing the password like this, but that doesn’t work either:
I know that some commands allow for the password to be provided as an argument, but I’d rather go through standard input. I’m looking for a quick and dirty way of piping a password into a command in bash.
Have you looked at autoexpect ? It doesn’t get much easier than that. You just just pass it the command and it will record everything you do and create the expect file for you.
8 Answers 8
How to use autoexpect to pipe a password into a command:
These steps are illustrated with an Ubuntu 12.10 desktop. The exact commands for your distribution may be slightly different.
This is dangerous because you risk exposing whatever password you use to anyone who can read the autoexpect script file.
DO NOT expose your root password or power user passwords by piping them through expect like this. Root kits WILL find this in an instant and your box is owned.
EXPECT spawns a process, reads text that comes in then sends text predefined in the script file.
- Make sure you have expect and autoexpect installed:
sudo apt-get install expect sudo apt-get install expect-dev
man expect man autoexpect
touch testfile.txt sudo chown root:root testfile.txt [enter password to authorize the changing of the owner]
touch myfile.txt autoexpect -f my_test_expect.exp sudo chown root:root myfile.txt [enter password which authorizes the chown to root] autoexpect done, file is my_test_expect.exp
sudo chown el my_test_expect.exp //make el the owner. sudo chmod 700 my_test_expect.exp //make file only readable by el.
set timeout -1 spawn sudo chown root:root myfile.txt match_max 100000 expect -exact "\[sudo\] password for el: " send -- "YourPasswordStoredInPlaintext\r" expect eof
expect my_test_expect.exp spawn sudo chown root:root myfile.txt [sudo] password for el:
ls -l -rw-r--r-- 1 root root 0 Dec 2 14:48 myfile.txt
It worked because it is root, and el never entered a password. If you expose your root, sudo, or power user password with this script, then acquiring root on your box will be easy. Such is the penalty for a security system that lets everybody in no questions asked.