How to get a password from a shell script without echoing

481,220

Solution 1

Here is another way to do it:

#!/bin/bash
# Read Password
echo -n Password: 
read -s password
echo
# Run Command
echo $password

The read -s will turn off echo for you. Just replace the echo on the last line with the command you want to run.

Solution 2

A POSIX compliant answer. Notice the use of /bin/sh instead of /bin/bash. (It does work with bash, but it does not require bash.)

#!/bin/sh
stty -echo
printf "Password: "
read PASSWORD
stty echo
printf "\n"

Solution 3

One liner:

read -s -p "Password: " password

Under Linux (and cygwin) this form works in bash and sh. It may not be standard Unix sh, though.

For more info and options, in bash, type "help read".

$ help read
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Read a line from the standard input and split it into fields.
  ...
  -p prompt output the string PROMPT without a trailing newline before
            attempting to read
  ...
  -s                do not echo input coming from a terminal

Solution 4

The -s option of read is not defined in the POSIX standard. See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html. I wanted something that would work for any POSIX shell, so I wrote a little function that uses stty to disable echo.

#!/bin/sh

# Read secret string
read_secret()
{
    # Disable echo.
    stty -echo

    # Set up trap to ensure echo is enabled before exiting if the script
    # is terminated while echo is disabled.
    trap 'stty echo' EXIT

    # Read secret.
    read "$@"

    # Enable echo.
    stty echo
    trap - EXIT

    # Print a newline because the newline entered by the user after
    # entering the passcode is not echoed. This ensures that the
    # next line of output begins at a new line.
    echo
}

This function behaves quite similar to the read command. Here is a simple usage of read followed by similar usage of read_secret. The input to read_secret appears empty because it was not echoed to the terminal.

[susam@cube ~]$ read a b c
foo \bar baz \qux
[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=bar c=baz qux
[susam@cube ~]$ unset a b c
[susam@cube ~]$ read_secret a b c

[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=bar c=baz qux
[susam@cube ~]$ unset a b c

Here is another that uses the -r option to preserve the backslashes in the input. This works because the read_secret function defined above passes all arguments it receives to the read command.

[susam@cube ~]$ read -r a b c
foo \bar baz \qux
[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=\bar c=baz \qux
[susam@cube ~]$ unset a b c
[susam@cube ~]$ read_secret -r a b c

[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=\bar c=baz \qux
[susam@cube ~]$ unset a b c

Finally, here is an example that shows how to use the read_secret function to read a password in a POSIX compliant manner.

printf "Password: "
read_secret password
# Do something with $password here ...

Solution 5

I found to be the the askpass command useful

password=$(/lib/cryptsetup/askpass "Give a password")

Every input character is replaced by *. See: Give a password ****

Share:
481,220
BD at Rivenhill
Author by

BD at Rivenhill

I'm working on the following projects (not necessarily in order): Software for automated trading (focusing on both high throughput and low latency) Robots

Updated on March 17, 2021

Comments

  • BD at Rivenhill
    BD at Rivenhill about 3 years

    I have a script that automates a process that needs access to a password protected system. The system is accessed via a command-line program that accepts the user password as an argument.

    I would like to prompt the user to type in their password, assign it to a shell variable, and then use that variable to construct the command line of the accessing program (which will of course produce stream output that I will process).

    I am a reasonably competent shell programmer in Bourne/Bash, but I don't know how to accept the user input without having it echo to the terminal (or maybe having it echoed using '*' characters).

    Can anyone help with this?