39

How can one read passwords in bash scripts in such a way that tools do not show it on a terminal?

(Changing font to black-on-black is easily worked around by copy & paste, so it's not solution.)

3
  • 6
    For anyone reading this: do NOT read in passwords with echo on and black-on-black. The password is still transmitted, and if the terminal doesn't know the terminal directives you've used, characters will echo visibly. Turn echo off. Use termios, stty, read -s, anything that does it.
    – Alexios
    Commented Mar 26, 2012 at 22:14
  • 1
    That's why I've wrote, that it is not a solution ;). Commented Mar 26, 2012 at 22:18
  • 1
    Indeed! Sometimes people skim questions and come to misguided conclusions. :)
    – Alexios
    Commented Mar 26, 2012 at 22:25

5 Answers 5

50

From help read:

-s        do not echo input coming from a terminal

For example, to prompt the user and read an arbitrary password into the variable passwd,

IFS= read -s -p 'Password please: ' passwd
2
  • 2
    Great. It's not written in my man read, I haven't check in help read. Good to know. Commented Mar 26, 2012 at 21:19
  • 5
    @GrzegorzWierzowiecki: You are viewing the wrong manual. you have to read the manual of bash i.e man bash and there you can find -s option Silent mode. If input is coming from a terminal, characters are not echoed. Commented Mar 27, 2012 at 6:34
11

I always used stty -echo to turn echoing off, then read and afterwards do stty echo (read more by viewing man of stty - i.e. man stty). This is more useful from a programmers perspective as you can turn echoing off and then read a password from a programming language such as Java, C(++), Python, etc. with their standard stdin "readers."

In bash, the usage could look like this:

echo -n "USERNAME: "; IFS= read -r uname
echo -n "PASSWORD: "; stty -echo; IFS= read -r passwd; stty echo; echo
program "$uname" "$passwd"
unset -v passwd    # get rid of passwd

Python, for example, would look like:

from sys import stdout
from os import system as term

uname = raw_input("USERNAME: ") # read input from stdin until [Enter] in 2
stdout.write("PASSWORD: ")
term("stty -echo") # turn echo off
try:
    passwd = raw_input()
except KeyboardInterrupt: # ctrl+c pressed
    raise SystemExit("Password attempt interrupted")
except EOFError: # ctrl+d pressed
    raise SystemExit("Password attempt interrupted")
finally:
    term("stty echo") # turn echo on again

print "username:", uname
print "password:", "*" * len(passwd)

I had to do this a lot of times in Python, so I know it pretty well from that perspective. This isn't very hard to translate to other languages, though.

1
  • I'm finding that stty -echo; sleep 3; stty echo makes any characters entered show up after the last command has completed.
    – hennes
    Commented Jul 8, 2022 at 19:07
0

If you're fine with adding an external dependency, you may use a password box provided by tools such as dialog or whiptail.

Whiptail

0

If running in an Apple-flavored zsh shell, builtins like read accept different args (BSD-flavored?), namely they interpret -p as another process to read from and you'll get the error

read: -p: no coprocess

In that case, you can make the prompt separately:

printf "Password please: "
IFS= read -s PASSWD

Where the password will be held in the envvar PASSWD.

-2

Your question reads kind of different "in a way like tools???" so I don't exactly know if this will work for you:

system1 $ passwd=abc123
system1 $ printf "%s\n" "${passwd//?/*}"
******

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .