在 Linux 脚本中隐藏终端上的用户输入

我有如下 bash 脚本:

#!/bin/bash


echo "Please enter your username";
read username;


echo "Please enter your password";
read password;

我希望当用户在终端上输入密码时,它不会显示出来(或者像 * * * * * * 这样的东西应该显示出来)。我该怎么做呢?

128635 次浏览

像这样给你的读取电话提供信息:

$ read -s PASSWORD
$ echo $PASSWORD

更新

如果你想为他们输入的每个字符输出一个 *,你可以这样做(使用 andreas 的 read -s解决方案) :

unset password;
while IFS= read -r -s -n1 pass; do
if [[ -z $pass ]]; then
echo
break
else
echo -n '*'
password+=$pass
fi
done

不要太花哨

echo "Please enter your username";
read username;


echo "Please enter your password";
stty -echo
read password;
stty echo

对于不使用 bash 或 read的某些特性的解决方案,可以使用 stty禁用 echo

stty_orig=$(stty -g)
stty -echo
read password
stty $stty_orig

下面是@SiegeX 的回答的一个变体,它可以使用传统的 Bourne shell (它不支持 +=分配)。

password=''
while IFS= read -r -s -n1 pass; do
if [ -z "$pass" ]; then
echo
break
else
printf '*'
password="$password$pass"
fi
done

下面是@SiegeX 为 bash 支持后退空间添加的优秀 *打印解决方案的一个变体; 这允许用户打印 用 ABC2键(Mac 上的 delete键)更正他们的条目,通常由密码提示支持:

#!/usr/bin/env bash


password=''
while IFS= read -r -s -n1 char; do
[[ -z $char ]] && { printf '\n'; break; } # ENTER pressed; output \n and break.
if [[ $char == $'\x7f' ]]; then # backspace was pressed
# Remove last char from output variable.
[[ -n $password ]] && password=${password%?}
# Erase '*' to the left.
printf '\b \b'
else
# Add typed char to output variable.
password+=$char
# Print '*' in its stead.
printf '*'
fi
done

注:

  • 至于为什么按退格键记录字符代码 0x7f: “在现代系统中,退格键通常映射到删除字符(ASCII 或 Unicode 中为0x7f)”译自: 美国《科学》杂志网站(https://en.wikipedia.org/wiki/Backspace) https://en.wikipedia.org/wiki/backspace :
  • \b \b用于 表现出... 的样子删除左侧的字符; 只需使用 \b将光标移动到左侧,但字符保持不变(非破坏性退格)。通过打印一个空格并再次向后移动,字符似乎已被擦除(谢谢,在 C 中的“ backspace”转义字符 b & # 39; b & # 39; 意外行为?)。

只有 POSIX shell 中(例如,在 Debian 和 Ubuntu 上的 sh,其中 shdash) ,使用 stty -echo方法(这是次优的,因为它打印的是 没什么) ,因为 read内建不支持 -s-n选项。

我总是喜欢使用安西转义字符:

echo -e "Enter your password: \x1B[8m"
echo -e "\x1B[0m"

8m使文本不可见,0m将文本重置为“正常”。-e 使 Ansi 转义成为可能。

唯一需要注意的是,您仍然可以复制和粘贴那里的文本,所以如果您真的想要安全性,那么您可能不应该使用这个。

它只是让人们在你输入密码的时候不会看到你的密码。之后别忘了关电脑。:)


注意:

只要支持 Ansi 转义序列,以上内容就是平台无关的。

但是,对于另一个 Unix 解决方案,您可以简单地告诉 read不要回显字符..。

printf "password: "
let pass $(read -s)
printf "\nhey everyone, the password the user just entered is $pass\n"

与@lesmana 的回答有点不同(但大多数是喜欢的)

stty -echo
read password
stty echo

隐藏回声 做你该做的 给 Echo 看看

获取用户名和密码

使它更清晰地阅读,但把它放在一个更好的位置在屏幕上

#!/bin/bash
clear
echo
echo
echo
counter=0
unset username
prompt="  Enter Username:"
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]; then
break
elif [ $char == $'\x08' ] && [ $counter -gt 0 ]; then
prompt=$'\b \b'
username="${username%?}"
counter=$((counter-1))
elif [ $char == $'\x08' ] && [ $counter -lt 1 ]; then
prompt=''
continue
else
counter=$((counter+1))
prompt="$char"
username+="$char"
fi
done
echo
unset password
prompt="  Enter Password:"
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]; then
break
elif [ $char == $'\x08' ] && [ $counter -gt 0 ]; then
prompt=$'\b \b'
password="${password%?}"
counter=$((counter-1))
elif [ $char == $'\x08' ] && [ $counter -lt 1 ]; then
echo
prompt="  Enter Password:"
continue
else
counter=$((counter+1))
prompt='*'
password+="$char"
fi
done

@ SiegeX 和@mklement0的优秀贡献的一个变体: 屏蔽用户输入; 处理后退空间; 但是只有用户输入的长度的后退空间(这样我们就不会抹去同一行中的其他字符)和处理控制字符,等等。.这个溶液是挖了这么久才找到 给你的!

#!/bin/bash
#
# Read and echo a password, echoing responsive 'stars' for input characters
# Also handles: backspaces, deleted and ^U (kill-line) control-chars
#
unset PWORD
PWORD=
echo -n 'password: ' 1>&2
while true; do
IFS= read -r -N1 -s char
# Note a NULL will return a empty string
# Convert users key press to hexadecimal character code
code=$(printf '%02x' "'$char") # EOL (empty char) -> 00
case "$code" in
''|0a|0d) break ;;   # Exit EOF, Linefeed or Return
08|7f)  # backspace or delete
if [ -n "$PWORD" ]; then
PWORD="$( echo "$PWORD" | sed 's/.$//' )"
echo -n $'\b \b' 1>&2
fi
;;
15) # ^U or kill line
echo -n "$PWORD" | sed 's/./\cH \cH/g' >&2
PWORD=''
;;
[01]?) ;;                        # Ignore ALL other control characters
*)  PWORD="$PWORD$char"
echo -n '*' 1>&2
;;
esac
done
echo
echo $PWORD