web-dev-qa-db-ja.com

Linuxスクリプトのターミナルでユーザー入力を非表示にする

次のようなbashスクリプトがあります。

#!/bin/bash

echo "Please enter your username";
read username;

echo "Please enter your password";
read password;

ユーザーが端末でパスワードを入力するときに、パスワードが表示されないようにする必要があります(または*******のようなもの)が表示されるようにします。どうすればこれを達成できますか?

109
JP19

次のように読み取り呼び出しに-sを指定するだけです。

$ read -s PASSWORD
$ echo $PASSWORD
244
Andreas Wong

更新

入力する文字ごとに*を出力して空想を得たい場合は、次のようなことができます(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
23
SiegeX

bashまたはreadの特定の機能なしで機能するソリューションの場合、sttyを使用してエコーを無効にできます。

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

@SiegeXのbashの優れた*- printingソリューションのバリエーションがありますバックスペースのサポートが追加されました。これにより、ユーザーは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

注意:

  • バックスペースを押すと文字コード0x7fが記録される理由について:「最新のシステムでは、バックスペースキーは多くの場合、削除文字(ASCIIまたはUnicodeの0x7f)にマップされます」 https://en.wikipedia.org/wiki/Backspace
  • \b \bは、左側の文字を削除する外観を与えるために必要です。 \bを使用すると、カーソルは左に移動しますが、文字はそのまま残ります(nondestructivebackspace)。スペースを印刷して再び戻ると、文字は消去されたように見えます(ありがとう、 Cの「バックスペース」エスケープ文字 '\ b'、予期しない動作? )。

POSIXのみシェル(たとえば、DebianおよびUbuntuのshshである場合、dash)では、stty -echoアプローチを使用(印刷されるため、最適ではありませんnothing)。これは、組み込み_readオプションが-sおよび-nオプションをサポートしないためです。

8
mklement0

@lesmanaの答えとは少し異なります(ほとんどが似ています)

stty -echo
read password
stty echo

単純に:エコーを非表示にする

3
yerlilbilgin

以下は、従来のBourne Shell(+=割り当てをサポートしていない)で機能する@SiegeXの回答のバリエーションです。

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

私は常に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"
2
dylnmc

ユーザー名とパスワードを取得する

読みやすくするが、画面上のより良い位置に置く

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