Linux 스크립트에서 터미널의 사용자 입력 숨기기


121

다음과 같은 bash 스크립트가 있습니다.

#!/bin/bash

echo "Please enter your username";
read username;

echo "Please enter your password";
read password;

사용자가 단말기에 암호를 입력 할 때 표시되지 않아야합니다 (또는 *******와 같은 내용이 표시되어야 함). 어떻게해야합니까?


2
혼동을 막기위한 일반적인 참고 사항 :이 사용자 이름 / 암호는 Linux 사용자 이름 / 암호와 아무 관련이 없습니다. "암호 읽기"중에 사용자가 입력하는 데이터를 숨기는 방법을 찾고 있습니다.

나는 *그들이 암호를 입력 하는 동안 출력하여 멋지게 만들고 싶다면 업데이트를 추가했습니다
SiegeX

고맙습니다. 누군가가 알고 있다면 한 가지 질문이 있습니다. 이것은 자동으로 .bash_history로 들어가는 것을 막을까요?


2
나는 그것이 할 것이라고 생각하지 않는다. bash_history는 당신의 명령만을 캡처하고, 당신의 명령을 실행 한 후에 일어나는 일은 캡처하지 않는다.
Andreas Wong

답변:


272

다음과 같이 읽기 호출에 -s를 제공하십시오.

$ read -s PASSWORD
$ echo $PASSWORD

9
나는이 방법이 더 좋다. 일일 한도에 도달하지 않으면 투표하겠습니다
SiegeX 2010

4
컨텍스트를 제공하려면 입력을 입력하는 동안 아무것도-s 표시 하지 않습니다 . ( -s은 POSIX가 아닌 확장이므로 ashBusyBox와 함께 제공 되는 셸 과 같은 모든 셸이 지원하는 것은 아닙니다 . ssty -echo이러한 셸 에서 접근 방식을 사용하십시오. )
mklement0

3
@electron man페이지의 어떤 것도 실제로 -s텍스트 색상을 배경색과 동일하게 설정 한다고 제안 하지 않습니다 . 그냥 "조용히 울림"입니다. ss64.com/bash/read.html Silent mode. If input is coming from a terminal, characters are not echoed.
Andreas Wong

2
@electron 내 상자에서 테스트했는데 커서가 움직이지 않을뿐만 아니라 암호를 입력 한 줄을 강조 표시하려고 할 때 나중에 붙여 넣을 수없는 것 같습니다. 책의 내용이 사실이라면 둘 다 일어나야합니다. 나는 아마도 다른 종류의 셸을 추측하고 있습니다 (bash 4.1.2 (1)을 사용했습니다).
Andreas Wong

1
@DominykasMostauskis 예,하지만 레이블은 bash 용이므로 솔루션입니다. 이것이 작동하지 않는 쉘 변형이
Andreas Wong

25

최신 정보

입력하는 *각 문자에 대해 를 출력하여 멋지게 만들고 싶다면 다음과 같이 할 수 있습니다 (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

IFS=$'\n'실제로 암호 입력을 완료 할 수 있어야 합니다. 그렇지 않으면 좋다. 매우 영리한.
sorpigal 2010

2
IFS=$'\n'읽기의 기본 구분 기호가이므로 설정할 필요가 없습니다 -d $'\n'. 줄 바꿈에서 발생하는 nul 문자열에서 중단되는 if 문은 암호를 완료 할 수 있도록합니다.
SiegeX 2010

bash 3.x를 사용하여 FreeBSD에서 테스트 한 결과, 그렇지 않습니다. 3.1.17로 Linux에서 테스트하면 결과가 나옵니다. 지금은 BSD 상자가 없지만 내 호기심을 위해 이것을 확인하려고 노력할 것입니다.
sorpigal 2010

@Sorpigal : 흥미 롭군요. 무엇을 알아 냈는지 알려주세요. 이식성에 대한 모든 것
SiegeX 2010

2
나는 그것을있어. 내 FreeBSD의 시험은 복사 한 가지 중요한 차이를 포함 lesmana의 게시물의 원래 잘못된 편집에서 붙여 넣은 코드를 기반으로했다 : 당신은 있었다 통과 read-d ''. 나중에 Linux에서 다시 시도했을 때 다시 게시 된 버전을 사용했습니다. -d ''물론 생략하면 FreeBSD에서도 똑같이 작동합니다! 나는 실제로 여기서 일하는 신비한 플랫폼 마법이 없다는 사실에 상당히 안심합니다.
sorpigal

17

bash없이 작동하는 솔루션 또는 에코를 비활성화 read하는 stty데 사용할 수있는 특정 기능

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

9

여기 에 백 스페이스 지원이 추가 된 @SiegeX의 우수한 *인쇄 솔루션에 대한 변형이 있습니다 . 이렇게하면 일반적으로 암호 프롬프트에서 지원하는 것처럼 사용자가 키 ( Mac의 경우 키)사용하여 항목수정할 수 있습니다 .bash backspacedelete

#!/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 또는 유니 코드의 0x7f)에 매핑됩니다." https://en.wikipedia.org/wiki/Backspace
  • \b \b왼쪽의 문자를 삭제하는 모양제공하는 데 필요합니다 . 를 사용 \b하면 커서가 왼쪽으로 이동하지만 문자는 그대로 둡니다 ( 비파괴 백 스페이스). 공백을 인쇄하고 다시 뒤로 이동하면 문자가 지워진 것처럼 보입니다 (감사합니다. C 의 "백 스페이스"이스케이프 문자 '\ b', 예기치 않은 동작? ).

A의 POSIX 전용 (예를 들어, 쉘 sh데비안과 우분투에 sh있다 dash), 사용 stty -echo방법 (가 인쇄하지 않기 때문에, 차선책이다 아무것도 )이 있기 때문에, read내장은 지원하지 않습니다 -s-n옵션을.


감사합니다, @Dylan. 지금까지 입력 한 암호에서 마지막 문자를 제거하는 코드가 단순화 될 수 있음을 깨달았습니다. 업데이트를 참조하십시오.
mklement0

3

@lesmana의 답변과 약간 다릅니다 (그러나 대부분 비슷합니다)

stty -echo
read password
stty echo

간단하게 : 에코 숨기기


이것이 @lesmana의 대답 보다 나은 이유를 설명 할 수 있습니까 ? 다른 stty호출에 대한 오버 헤드가 적고 스택의 변수가 하나 더 적 으면 더 간단 합니다. 에코 만 제거하고 에코 만 복원합니다. 이것이 다른 stty설정을 뒤엎을 수있는 가능한 방법이 있습니까? Lesmana는 모든 설정을 보존합니다.
Jeff Puckett

2

다음은 기존 Bourne 셸 ( +=할당을 지원하지 않음)에서 작동하는 @SiegeX의 답변 변형입니다 .

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

전통적인 Bourne 쉘 (또는 POSIX 호환 일)도 인식 할 것 [[ ... ]],이나 그 것이다 read내장은 가지고 -s-n옵션을. 따라서 귀하의 코드는 dash예를 들어 에서 작동하지 않습니다 . (이는 OSX와 같이 sh실제로 호출 될 때 대부분의 바 bashbashsh
시즘을

2
피드백을 주셔서 감사합니다. 싱글로 전환 [했지만 read이러한 옵션 이 없으면 할 수있는 일이별로 없습니다 .
tripleee 2014-04-08

2

저는 항상 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"

1

사용자 이름 및 비밀번호 가져 오기

더 명확하게 읽을 수 있지만 화면에서 더 나은 위치에 배치하십시오.

#!/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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.