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

ni65a41a  于 2022-12-22  发布在  Linux
关注(0)|答案(9)|浏览(206)

我有如下的bash脚本:

#!/bin/bash

echo "Please enter your username";
read username;

echo "Please enter your password";
read password;

我希望用户在终端上输入密码时,密码不显示(或者显示*******之类的内容),如何实现呢?

kninwzqo

kninwzqo1#

只需向read调用提供-s,如下所示:

$ read -s PASSWORD
$ echo $PASSWORD
j2cgzkjk

j2cgzkjk2#

更新

如果你想为输入的每个字符输出一个*,你可以这样做(使用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
w46czmvw

w46czmvw3#

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

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

对于在整个脚本运行期间禁止所有用户输入的bash脚本,请设置退出处理程序以确保tty设置被恢复。

stty_orig=$(stty -g)
trap "stty ${stty_orig}" EXIT
stty -echo
uqdfh47h

uqdfh47h4#

这是@SiegeX优秀的*的一个变体--bash的打印解决方案增加了对退格键的支持;这允许用户**使用backspace密钥(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

注:

仅支持POSIX的shell中(例如,Debian和Ubuntu上的sh,其中shdash),使用stty -echo方法(这是次优的,因为它打印 * nothing *),因为read内置不支持-s-n选项。

eulz3vhy

eulz3vhy5#

与@lesmana的回答有点不同(但基本相似)

stty -echo
read password
stty echo

简单地说:隐藏echo你东西显示echo吗

xxe27gdn

xxe27gdn6#

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

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"
lnxxn5zx

lnxxn5zx7#

下面是@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
rqenqsqc

rqenqsqc8#

获取用户名和密码
使其更清晰地阅读,但把它放在屏幕上更好的位置

#!/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
vfwfrxfs

vfwfrxfs9#

@SiegeX和@mklement0的杰出贡献的变体:屏蔽用户输入;句柄回退;但是只退格用户输入的长度(这样我们就不会删除同一行上的其他字符)和处理控制字符等......经过这么多的挖掘,here找到了这个解决方案!

#!/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

相关问题