Как получить пароль из оболочки без вывода в терминал?
У меня есть скрипт, который автоматизирует процесс и требует доступа к защищенной паролем системе. Доступ к системе осуществляется через командную программу, которая принимает пароль пользователя в качестве аргумента.
Я хотел бы запросить у пользователя ввод пароля, присвоить его переменной оболочки и затем использовать эту переменную для формирования командной строки программы доступа (которая, разумеется, будет выводить данные в поток, который я буду обрабатывать).
Я довольно неплохо разбираюсь в программировании на оболочке Bourne/Bash, но не знаю, как принять ввод от пользователя так, чтобы он не отображался в терминале (или чтобы отображался с использованием символов '*').
Может быть, кто-то сможет мне помочь?
5 ответ(ов)
Вот POSIX-совместимый ответ. Обратите внимание на использование /bin/sh
вместо /bin/bash
. Скрипт работает и с bash, но не требует его.
#!/bin/sh
stty -echo
printf "Пароль: "
read PASSWORD
stty echo
printf "\n"
Этот скрипт временно отключает вывод символов на экран при вводе пароля, а затем снова включает его.
Однострочник для ввода пароля без отображения:
read -s -p "Пароль: " password
Этот подход работает в bash и sh под Linux (и Cygwin). Однако может не поддерживаться стандартным Unix sh.
Для получения дополнительной информации и параметров в bash введите "help read".
$ help read
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Считывает строку из стандартного ввода и разбивает ее на поля.
...
-p prompt выводит строку PROMPT без завершающего перевода строки перед попыткой считывания
...
-s не выводить ввод, поступающий из терминала
Опция -s
команды read
не определена в стандарте POSIX. Для подробной информации посмотрите документацию. Поскольку я хотел, чтобы решение работало в любом POSIX-совместимом шелле, я написал небольшую функцию, которая использует stty
для отключения эха.
# Чтение секретной строки
read_secret() {
# Устанавливаем trap, чтобы гарантировать, что эхо будет включено перед выходом,
# если скрипт завершится, пока эхо отключено.
trap 'stty echo' EXIT
# Отключаем эхо.
stty -echo
# Читаем секрет.
read "$@"
# Включаем эхо.
stty echo
trap - EXIT
# Печатаем новую строку, так как нажатая пользователем клавиша Enter
# не отображается. Это гарантирует, что следующая строка вывода начнётся с новой строки.
echo
}
Эта функция работает очень похоже на команду read
. Вот простой пример использования read
, за которым следует подобное использование read_secret
. Ввод для read_secret
кажется пустым, потому что он не отображается в терминале.
[susam@cube ~]$ read a b c
foo \bar baz \qux
[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=bar c=baz qux
[susam@cube ~]$ unset a b c
[susam@cube ~]$ read_secret a b c
[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=bar c=baz qux
[susam@cube ~]$ unset a b c
Вот ещё один пример, который использует опцию -r
, чтобы сохранить обратные слэши во вводе. Это работает, потому что функция read_secret
, как показано выше, передаёт все аргументы, которые она получает, команде read
.
[susam@cube ~]$ read -r a b c
foo \bar baz \qux
[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=\bar c=baz \qux
[susam@cube ~]$ unset a b c
[susam@cube ~]$ read_secret -r a b c
[susam@cube ~]$ echo a=$a b=$b c=$c
a=foo b=\bar c=baz \qux
[susam@cube ~]$ unset a b c
Наконец, вот пример, который демонстрирует, как использовать функцию read_secret
для чтения пароля в соответствии с требованиями POSIX.
printf "Пароль: "
read_secret password
# Сделайте что-то с $password здесь ...
Использование команды askpass
действительно может быть очень полезным. Вот пример, как её можно применить для запроса пароля:
password=$(/lib/cryptsetup/askpass "Введите пароль")
При этом каждое введенное вами символ будет заменено на *
, что обеспечивает дополнительную безопасность. Например, если ввести пароль "1234", в интерфейсе вы увидите:
Введите пароль ****
Таким образом, askpass
помогает скрыть вводимый пароль от посторонних глаз.
Вы также можете запросить пароль, не устанавливая переменную в текущей оболочке, используя следующий синтаксис:
$(read -s;echo $REPLY)
Например, это можно использовать так:
my-command --set password=$(read -sp "Пароль: ";echo $REPLY)
Вы также можете добавить несколько запрашиваемых значений с переводом строки, сделав это следующим образом:
my-command --set user=$(read -sp "`echo $'\n '`Пользователь: ";echo $REPLY) --set password=$(read -sp "`echo $'\n '`Пароль: ";echo $REPLY)
Этот подход позволяет вводить значения без отображения введенных символов.
Как запросить ввод Yes/No/Cancel в скрипте оболочки Linux?
Как объявить и использовать логические переменные в shell-скрипте?
Как проверить, содержит ли строка подстроку в Bash
Как выводить команды оболочки по мере их выполнения
Разница между sh и Bash