Sometimes we may need to hide the user input so that they won’t be shown in the terminal. This is especially useful when our script requires a password from users.
tl;dr
1. read -s
We can use the command read
with option -s
to read the password. It would not echo the input coming from the terminal when the option -s
is specified.
For example:
#!/bin/bash
read -s -p "Enter password: " password
echo
echo "password: $password"
Example output:
noob@learnfromnoobs:~$ ./input_password_read.sh
Enter password:
password: 123456
For more information, please refer to read --help
.
2. stty
We can just wrap stty -echo
and stty echo
between our code block that asks for user input. It turns off echo for the code block asking for user input, so nothing is output for that part.
For example:
#!/bin/bash
stty -echo
echo -n "Enter password: "
read password
echo
echo "password: $password"
stty echo
Example output:
noob@learnfromnoobs:~$ ./input_password_stty.sh
Enter password:
password: 123456
Notice that we cannot see our input when we type our password. The results for both methods should be exactly the same.
That’s it! Of course, don’t use a password like “123456” in our case!
ts;wm
What is stty?
According to the manpage of stty, stty is a utility to change and print terminal line settings.
If stty is run without arguments, it prints the baud rate, line discipline number and line settings that have been changed from the values set by ‘stty sane’.
noob@learnfromnoobs:~$ stty
speed 38400 baud; line = 0;
-brkint ixoff -imaxbel iutf8
Let’s try to turn off echo and then run stty
again. As the echo is turned off, it is normal that you cannot see yourself typing stty
. We can see that “-echo” now appears at the bottom line, indicating the echo is turned off.
noob@learnfromnoobs:~$ stty -echo
noob@learnfromnoobs:~$ speed 38400 baud; line = 0;
-brkint ixoff -imaxbel iutf8
-echo
We can view all current stty configurations using the command stty -a
.
noob@learnfromnoobs:~$ stty -a
speed 38400 baud; rows 46; columns 104; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff -iuclc -ixany -imaxbel
iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho
-extproc
For more information about stty, please refer to man stty
or info stty
.
Using asterisk instead of blank
Note that this approach will expose the length of your password. I would prefer just hiding the user input completely. But if you really want, you can try the approaches below.
1. systemd-ask-password
if available
If the utility systemd-ask-password
is available, we can just use it to get the password.
Note that there is a default 60-second timeout. We can specify the option --timeout=0
if we don’t want any timeout.
#!/bin/bash
password=`systemd-ask-password "Enter password:"`
echo "password: $password"
Example output:
noob@learnfromnoobs:~$ ./input_password_systemd.sh
Enter password: ******
password: 123456
2. Write it yourself.
If you don’t like the systemd-ask-password
approach (or simply want to use a character other than ‘*’), you can write your implementation. This can also be a fun exercise.
Our implementation should allow deleting characters.
To accomplish this, our script needs to be able to handle backspace and EOL.
We also need to make sure that we are not deleting the prompt.
#!/bin/bash
unset password
unset chartCount
echo -n "Enter password: "
while IFS= read -r -n1 -s char; do
case "$char" in
$'\0')
break
;;
$'\177')
if [ ${#password} -gt 0 ]; then
echo -ne "\b \b"
password=${password::-1}
fi
;;
*)
chartCount=$((chartCount+1))
echo -n '*'
password+="$char"
;;
esac
done
echo
echo "password: $password"
Example output:
noob@learnfromnoobs:~$ ./input_password_asterisk.sh
Enter password: ******
password: 123456
Some notes for the script:
IFS=
is used in the while loop to make sure the loop won’t break on passwords that contain spaces. For more information, look for “IFS” inman bash
.-r
is used in theread
command to allow passwords containing backslashes.echo -ne "\b \b"
is used to erase 1 character in the password.\b
moves the cursor left for 1 character. Then we output a space character ” “. And finally using\b
to move the cursor 1 character left again. These are the complete actions of erasing 1 character. The option-e
is needed to enable interpretation of backslash escapes.
Conclusion
In summary, we have provided 4 methods to hide password or user input in bash:
- Using
read -s
- Using
stty -echo
- Using
systemd-ask-password
- Write your own implementation
No matter which method you have chosen finally, I hope you enjoyed this article.
Keep learning and have fun!