Diese Antwort sollte zugunsten der @ eclectic923-Kern-Rubinlösung abgelehnt werden.
Notapatch
183
Man kann auch Kern Rubin verwenden.
$ ri IO.noecho
(from ruby core)
------------------------------------------------------------------------------
io.noecho {|io| }
------------------------------------------------------------------------------
Yields self with disabling echo back.
STDIN.noecho(&:gets)
will read andreturn a line without echo back.
Für 1.9.3 (und höher) müssen Sie require 'io/console'Ihren Code hinzufügen .
Wie die anderen erwähnen, können Sie IO#noechofür Ruby> = 1.9 verwenden. Wenn Sie Unterstützung für 1.8 readwünschen , können Sie die integrierte Shell-Funktion verwenden:
Jetzt ist es so einfach, ein Passwort zu erhalten wie:
@password = get_password("Enter your password here: ")
Hinweis: Bei der oben verwendeten Implementierung readtreten Probleme auf, wenn Sie (oder ein anderer Client von get_password) spezielle Shell-Zeichen in der Eingabeaufforderung (z. B. $/ "/ '/ etc) weitergeben. Im Idealfall sollten Sie die Eingabeaufforderungszeichenfolge maskieren, bevor Sie sie an die Shell weitergeben. Ist Shellwordsin Ruby 1.8 leider nicht verfügbar. Glücklicherweise ist es einfach, die relevanten Bits selbst (speziell shellescape) zurück zu portieren . Damit können Sie diese geringfügige Änderung vornehmen:
defget_password(prompt="Password: ")`read -s -p #{Shellwords.shellescape(prompt)} password; echo $password`.chomp
end
Ich erwähnte ein paar Probleme mit der Verwendung von read -s -pin einem Kommentar unten:
Nun, der 1.8-Fall ist ein bisschen ruckelig; Backslashes sind nicht zulässig, es sei denn, Sie drücken zweimal Backslash: "Das Backslash-Zeichen" \ "kann verwendet werden, um spezielle Bedeutungen für das nächste gelesene Zeichen und für die Fortsetzung der Zeile zu entfernen." Außerdem: "Die Zeichen im Wert der IFS-Variablen werden verwendet, um die Zeile in Wörter aufzuteilen." Dies sollte wahrscheinlich für die meisten kleinen Skripte in Ordnung sein, aber für größere Anwendungen möchten Sie wahrscheinlich etwas Robusteres.
Wir können einige dieser Probleme beheben, indem wir die Ärmel hochkrempeln und dies mit aller Kraft tun stty(1). Ein Überblick darüber, was wir tun müssen:
Speichern Sie die aktuellen Terminaleinstellungen
Schalten Sie das Echo aus
Drucken Sie die Eingabeaufforderung aus und erhalten Sie Benutzereingaben
Stellen Sie die Terminaleinstellungen wieder her
Wir müssen auch darauf achten, die Terminaleinstellungen wiederherzustellen, wenn sie durch Signale und / oder Ausnahmen unterbrochen werden. Der folgende Code verarbeitet Jobsteuerungssignale (SIGINT / SIGTSTP / SIGCONT) ordnungsgemäß, während er weiterhin mit allen vorhandenen Signalhandlern spielt:
require'shellwords'defget_password(prompt="Password: ")
new_sigint = new_sigtstp = new_sigcont = nil
old_sigint = old_sigtstp = old_sigcont = nil# save the current terminal configuration
term = `stty -g`.chomp
# turn of character echo`stty -echo`
new_sigint = Proc.new do`stty #{term.shellescape}`
trap("SIGINT", old_sigint)
Process.kill("SIGINT", Process.pid)
end
new_sigtstp = Proc.new do`stty #{term.shellescape}`
trap("SIGCONT", new_sigcont)
trap("SIGTSTP", old_sigtstp)
Process.kill("SIGTSTP", Process.pid)
end
new_sigcont = Proc.new do`stty -echo`
trap("SIGCONT", old_sigcont)
trap("SIGTSTP", new_sigtstp)
Process.kill("SIGCONT", Process.pid)
end# set all signal handlers
old_sigint = trap("SIGINT", new_sigint) ||"DEFAULT"
old_sigtstp = trap("SIGTSTP", new_sigtstp) ||"DEFAULT"
old_sigcont = trap("SIGCONT", new_sigcont) ||"DEFAULT"
print prompt
password = STDIN.gets.chomp
puts
password
ensure# restore term and handlers`stty #{term.shellescape}`
trap("SIGINT", old_sigint)
trap("SIGTSTP", old_sigtstp)
trap("SIGCONT", old_sigcont)
end
Nun, der 1.8-Fall ist ein bisschen ruckelig; Backslashes sind nur zulässig, wenn Sie zweimal auf Backslash klicken: "Das Backslash-Zeichen" \ "kann verwendet werden, um spezielle Bedeutungen für das nächste gelesene Zeichen und für die Fortsetzung der Zeile zu entfernen." Außerdem: "Die Zeichen im Wert der IFS-Variablen werden verwendet, um die Zeile in Wörter aufzuteilen." Dies sollte wahrscheinlich für die meisten kleinen Skripte in Ordnung sein, aber Sie möchten wahrscheinlich etwas Robusteres für größere Anwendungen.
Charles
16
Ab Ruby Version 2.3.0 können Sie die folgende IO#getpassMethode verwenden:
Wie kann man mit getpass ein bestimmtes Zeichen wie * wiedergeben?
João Ramires
5
Für Ruby Version 1.8 (oder Ruby <1.9) habe ich die von @Charles erwähnte Read Shell verwendet.
Wenn Sie den Code eingeben, der gerade ausreicht, um zur Eingabe von Benutzername und Kennwort aufzufordern, wobei der Benutzername während der Eingabe auf dem Bildschirm angezeigt wird, das eingegebene Kennwort jedoch stumm bleibt.
Antworten:
Beste Methode aus der Antwort von @ eclectic923:
require 'io/console' password = STDIN.noecho(&:gets).chomp
Für 1.9.3 (und höher) müssen Sie
require 'io/console'
Ihren Code hinzufügen .Ursprüngliche Antwort:
Ruby " Passwort " ist eine weitere Alternative.
quelle
Man kann auch Kern Rubin verwenden.
$ ri IO.noecho (from ruby core) ------------------------------------------------------------------------------ io.noecho {|io| } ------------------------------------------------------------------------------ Yields self with disabling echo back. STDIN.noecho(&:gets) will read and return a line without echo back.
Für 1.9.3 (und höher) müssen Sie
require 'io/console'
Ihren Code hinzufügen .require 'io/console' text = STDIN.noecho(&:gets)
quelle
require 'io/console'
Ihren Code hinzufügen . Viel besser als jede Edelsteinoption normalerweise.tmp.rb:2:in 'noecho': Bad file descriptor (Errno::EBADF) from tmp.rb:2:in <main>
Es gibt eine Bibliothek namens Highline, die so funktioniert:
require 'rubygems' require 'highline/import' password = ask("Enter password: ") { |q| q.echo = false } # do stuff with password
quelle
Wie die anderen erwähnen, können Sie
IO#noecho
für Ruby> = 1.9 verwenden. Wenn Sie Unterstützung für 1.8read
wünschen , können Sie die integrierte Shell-Funktion verwenden:begin require 'io/console' rescue LoadError end if STDIN.respond_to?(:noecho) def get_password(prompt="Password: ") print prompt STDIN.noecho(&:gets).chomp end else def get_password(prompt="Password: ") `read -s -p "#{prompt}" password; echo $password`.chomp end end
Jetzt ist es so einfach, ein Passwort zu erhalten wie:
@password = get_password("Enter your password here: ")
Hinweis: Bei der oben verwendeten Implementierung
read
treten Probleme auf, wenn Sie (oder ein anderer Client vonget_password
) spezielle Shell-Zeichen in der Eingabeaufforderung (z. B.$
/"
/'
/ etc) weitergeben. Im Idealfall sollten Sie die Eingabeaufforderungszeichenfolge maskieren, bevor Sie sie an die Shell weitergeben. IstShellwords
in Ruby 1.8 leider nicht verfügbar. Glücklicherweise ist es einfach, die relevanten Bits selbst (speziellshellescape
) zurück zu portieren . Damit können Sie diese geringfügige Änderung vornehmen:def get_password(prompt="Password: ") `read -s -p #{Shellwords.shellescape(prompt)} password; echo $password`.chomp end
Ich erwähnte ein paar Probleme mit der Verwendung von
read -s -p
in einem Kommentar unten:Wir können einige dieser Probleme beheben, indem wir die Ärmel hochkrempeln und dies mit aller Kraft tun
stty(1)
. Ein Überblick darüber, was wir tun müssen:Wir müssen auch darauf achten, die Terminaleinstellungen wiederherzustellen, wenn sie durch Signale und / oder Ausnahmen unterbrochen werden. Der folgende Code verarbeitet Jobsteuerungssignale (SIGINT / SIGTSTP / SIGCONT) ordnungsgemäß, während er weiterhin mit allen vorhandenen Signalhandlern spielt:
require 'shellwords' def get_password(prompt="Password: ") new_sigint = new_sigtstp = new_sigcont = nil old_sigint = old_sigtstp = old_sigcont = nil # save the current terminal configuration term = `stty -g`.chomp # turn of character echo `stty -echo` new_sigint = Proc.new do `stty #{term.shellescape}` trap("SIGINT", old_sigint) Process.kill("SIGINT", Process.pid) end new_sigtstp = Proc.new do `stty #{term.shellescape}` trap("SIGCONT", new_sigcont) trap("SIGTSTP", old_sigtstp) Process.kill("SIGTSTP", Process.pid) end new_sigcont = Proc.new do `stty -echo` trap("SIGCONT", old_sigcont) trap("SIGTSTP", new_sigtstp) Process.kill("SIGCONT", Process.pid) end # set all signal handlers old_sigint = trap("SIGINT", new_sigint) || "DEFAULT" old_sigtstp = trap("SIGTSTP", new_sigtstp) || "DEFAULT" old_sigcont = trap("SIGCONT", new_sigcont) || "DEFAULT" print prompt password = STDIN.gets.chomp puts password ensure # restore term and handlers `stty #{term.shellescape}` trap("SIGINT", old_sigint) trap("SIGTSTP", old_sigtstp) trap("SIGCONT", old_sigcont) end
quelle
Ab Ruby Version 2.3.0 können Sie die folgende
IO#getpass
Methode verwenden:require 'io/console' password = STDIN.getpass("Password:")
Siehe die getpass- Methode in der Standardbibliotheksdokumentation.
quelle
Für Ruby Version 1.8 (oder Ruby <1.9) habe ich die von @Charles erwähnte Read Shell verwendet.
Wenn Sie den Code eingeben, der gerade ausreicht, um zur Eingabe von Benutzername und Kennwort aufzufordern, wobei der Benutzername während der Eingabe auf dem Bildschirm angezeigt wird, das eingegebene Kennwort jedoch stumm bleibt.
userid = `read -p "User Name: " uid; echo $uid`.chomp passwd = `read -s -p "Password: " password; echo $password`.chomp
quelle