Benutzereingaben auf dem Terminal im Linux-Skript ausblenden


121

Ich habe ein Bash-Skript wie das folgende:

#!/bin/bash

echo "Please enter your username";
read username;

echo "Please enter your password";
read password;

Ich möchte, dass wenn der Benutzer das Passwort auf dem Terminal eingibt, es nicht angezeigt wird (oder so etwas wie *******). Wie erreiche ich das?


2
Allgemeiner Hinweis, um Verwirrung zu vermeiden: Dieser Benutzername / dieses Passwort hat nichts mit dem Linux-Benutzernamen / Passwort zu tun. Ich suche nur nach einer Möglichkeit, die Daten zu verbergen, die der Benutzer beim "Lesen des Passworts" eingibt.

Ich habe ein Update hinzugefügt, wenn Sie Lust haben, indem Sie etwas ausgeben, *während Sie das Passwort eingeben
SiegeX

Vielen Dank. Eine Frage, wenn jemand weiß - wird dies automatisch verhindern, dass es in .bash_history geht?


2
Ich glaube nicht, dass bash_history nur Ihren Befehl erfasst. Was passiert, nachdem Sie Ihren Befehl ausgeführt haben, wird nicht erfasst?
Andreas Wong

Antworten:


270

Geben Sie Ihren Leseanruf einfach wie folgt ein:

$ read -s PASSWORD
$ echo $PASSWORD

9
Ich mag diesen Weg besser. Ich würde dich abstimmen, wenn ich mein Tageslimit nicht erreichen würde
SiegeX

4
Kontext bereitstellen: -sZeigt nichts an, während die Eingabe eingegeben wird. ( -sist eine Nicht-POSIX-Erweiterung, daher wird sie nicht von allen Shells unterstützt, z. B. der ashmit BusyBox ssty -echo
gelieferten

3
@electron Nichts auf der manSeite deutet darauf hin, dass -sdie Textfarbe der Hintergrundfarbe entspricht. Es hallt nur "lautlos". ss64.com/bash/read.html Silent mode. If input is coming from a terminal, characters are not echoed.
Andreas Wong

2
@electron Ich habe auf meiner Box getestet, nicht nur, dass sie den Cursor nicht bewegt. Wenn ich versuche, die Zeile hervorzuheben, in die ich mein Passwort eingegeben habe, kann ich sie später scheinbar nicht einfügen. Beides sollte passieren, wenn das, was das Buch sagt, wahr ist. Ich vermute vielleicht einen anderen Geschmack der Schale (ich habe Bash 4.1.2 (1) verwendet).
Andreas Wong

1
@DominykasMostauskis ja, aber das Etikett ist für Bash, daher die Lösung. Es gibt wahrscheinlich Tonnen von Shell-Varianten, bei denen dies nicht funktioniert :)
Andreas Wong

25

Aktualisieren

Wenn Sie Lust haben möchten, indem Sie *für jedes eingegebene Zeichen ein ausgeben , können Sie Folgendes tun (mit der read -sLösung von andreas ):

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

Ohne ausgefallen zu sein

echo "Please enter your username";
read username;

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

Es sollte IFS=$'\n'so sein, dass Sie die Eingabe des Passworts tatsächlich beenden können . Ansonsten schön; sehr schlau.
Sorpigal

2
Keine Einstellung erforderlich, IFS=$'\n'da das Standardtrennzeichen von read ist -d $'\n'. Die if-Anweisung zum Unterbrechen einer Nullzeichenfolge, die in einer neuen Zeile vorkommt, ermöglicht es ihnen, das Kennwort zu beenden.
SiegeX

Beim Testen auf FreeBSD mit bash 3.x finde ich, dass dies nicht der Fall ist. Das Testen unter Linux mit 3.1.17 liefert Ihre Ergebnisse. Ich habe momentan keine BSD-Box zur Hand, aber ich werde versuchen, dies morgen zu bestätigen, nur aus Neugier.
Sorpigal

@Sorpigal: Interessant, lass mich wissen, was du herausfindest. Ich bin alles über Portabilität
SiegeX

2
Ich habe es. Mein FreeBSD - Test auf dem Code basiert kopiert und eingefügt von Ihrem ursprünglichen verwechselt bearbeiten von Lesmana der Post, die einen wichtigen Unterschied enthält: Sie war vorbei readein -d ''. Als ich es später unter Linux erneut versuchte, verwendete ich die neu veröffentlichte Version. Wenn ich versuche wegzulassen -d '', funktioniert es natürlich identisch mit FreeBSD! Ich bin eigentlich ziemlich erleichtert, dass hier keine mysteriöse Plattformmagie am Werk ist.
Sorpigal

17

Für eine Lösung, die ohne Bash oder bestimmte Funktionen von funktioniert, können readSie das sttyEcho deaktivieren

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

9

Hier ist eine Variation der hervorragenden *Drucklösung von @ SiegeX für die bash Unterstützung von Backspace . Auf diese Weise kann der Benutzer seine Eingabe mit dem backspaceSchlüssel ( deleteSchlüssel auf einem Mac) korrigieren , wie dies normalerweise durch Kennwortabfragen unterstützt wird:

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

Hinweis:

  • Wenn Sie 0x7fdie Rücktaste drücken, wird der Zeichencode aufgezeichnet: "In modernen Systemen wird die Rücktaste häufig dem Löschzeichen zugeordnet (0x7f in ASCII oder Unicode)." Https://en.wikipedia.org/wiki/Backspace
  • \b \bwird benötigt, um den Anschein zu erwecken, als würde das Zeichen links gelöscht. Nur mit \bbewegt wird der Cursor nach links bewegt, das Zeichen bleibt jedoch intakt ( zerstörungsfreie Rücktaste). Wenn Sie ein Leerzeichen drucken und wieder zurückgehen, scheint das Zeichen gelöscht worden zu sein (danke, das Escapezeichen "\ b" in C, unerwartetes Verhalten? ).

Verwenden Sie in einer Nur-POSIX- Shell (z. B. shunter Debian und Ubuntu, wo dies der Fall shist dash) den stty -echoAnsatz (der nicht optimal ist, weil er nichts druckt ), da das integrierte readProgramm die Optionen -sund nicht unterstützt -n.


Danke, @ Dylan. Ich habe gerade festgestellt, dass der Code zum Entfernen des letzten Zeichens aus dem bisher eingegebenen Passwort vereinfacht werden kann - siehe Update.
mklement0

3

Ein bisschen anders als die Antwort von @ lesmana (aber meistens ähnlich)

stty -echo
read password
stty echo

einfach: echo ausblenden zeigen deine sachen echo


Können Sie erklären, warum dies besser ist als die Antwort von @ lesmana ? Ich sehe, es ist einfacher mit weniger Overhead für einen weiteren sttyAufruf und einer Variablen weniger auf dem Stapel - nur Echo wegnehmen und nur Echo wiederherstellen. Gibt es eine Möglichkeit, andere sttyEinstellungen zu stören ? Lesmana behält alle Einstellungen bei.
Jeff Puckett

2

Hier ist eine Variation der Antwort von @ SiegeX, die mit der traditionellen Bourne-Shell funktioniert (die keine Unterstützung für +=Zuweisungen bietet ).

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

Eine herkömmliche Bourne-Shell (oder eine POSIX-kompatible Shell) würde dies ebenfalls nicht erkennen [[ ... ]], und ihr readeingebautes System verfügt auch nicht über die Optionen -sund -n. Ihr Code funktioniert daher beispielsweise nicht dash. (Es wird auf Plattformen funktionieren, auf denen shes tatsächlich ist bash, wie unter OSX, wo bashbeim shAufrufen lediglich einige Standardoptionen geändert werden, während die meisten Bashismen weiterhin unterstützt werden.)
mklement0

2
Vielen Dank für [Ihr Feedback, auf Single umgestellt, aber natürlich kann ich nicht viel tun, wenn Ihnen readdiese Optionen fehlen.
Tripleee

2

Ich benutze immer gerne Ansi-Escape-Zeichen:

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

8m macht Text unsichtbar und 0m setzt Text auf "normal" zurück. Das -e macht Ansi-Flucht möglich.

Die einzige Einschränkung besteht darin, dass Sie den vorhandenen Text weiterhin kopieren und einfügen können. Daher sollten Sie ihn wahrscheinlich nicht verwenden, wenn Sie wirklich Sicherheit wünschen.

Damit können die Benutzer Ihre Passwörter beim Eingeben nicht einsehen. Lassen Sie Ihren Computer danach einfach nicht eingeschaltet. :) :)


HINWEIS:

Das Obige ist plattformunabhängig, solange es Ansi-Escape-Sequenzen unterstützt.

Bei einer anderen Unix-Lösung können Sie jedoch einfach festlegen read, dass die Zeichen nicht wiederholt werden sollen ...

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

1

Holen Sie sich Benutzername und Passwort

Machen Sie das Lesen klarer, aber platzieren Sie es besser über dem Bildschirm

#!/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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.