如何从shell脚本获取密码而不进行回显

BD *_*ill 384 bash shell scripting sh

我有一个脚本可以自动执行需要访问受密码保护的系统的进程.通过命令行程序访问系统,该程序接受用户密码作为参数.

我想提示用户键入他们的密码,将其分配给shell变量,然后使用该变量构建访问程序的命令行(这当然会产生我将处理的流输出).

我是Bourne/Bash中一个相当称职的shell程序员,但我不知道如何接受用户输入而不让它回显到终端(或者可能使用'*'字符回显).

有人能帮忙吗?

wsw*_*are 565

这是另一种方法:

#!/bin/bash
# Read Password
echo -n Password: 
read -s password
echo
# Run Command
echo $password
Run Code Online (Sandbox Code Playgroud)

read -s将为你关闭回声.只需将echo最后一行替换为您要运行的命令即可.

  • 有些shell允许你指定`read`命令的提示符:`read -s -p"密码:"password` (83认同)
  • 请注意,`read -s`不在POSIX中,如果你使用它,你的脚本依赖于bash.如果你想要符合POSIX标准,你应该使用下面建议的`stty -echo'解决方案,因为`stty`及其`echo`参数在POSIX中定义. (33认同)
  • 哦,`echo -n`也不在POSIX中.请改用"printf". (7认同)
  • 根据我的尝试:只使用`/ bin/bash`而不是`/ bin/sh`,只是为了清楚这一点. (4认同)
  • 我用 `echo "$REPLY" | 跟进它 sed -r 's/./*/g'` (甚至任意数量的星号)而不是空的 `echo` 让他们知道他们的密码输入已被看到(如果他们输入了一个。我有一个默认密码如果他们选择跳过我的特定脚本中的提示) (2认同)

小智 188

#!/bin/sh
stty -echo
printf "Password: "
read PASSWORD
stty echo
printf "\n"
Run Code Online (Sandbox Code Playgroud)

  • 不,真的,如果你想要符合POSIX标准,请使用`stty`.这个答案中的代码在bash上运行得非常完美,但实际上在符合POSIX的_all_ shell上运行. (46认同)
  • @PypeBros您可以捕获中断以重新打开回显:`trap 'stty echo' INT`。这将出现在包装此功能的脚本或函数的开头。 (4认同)
  • 不幸的是,在stty -echo发生后用CTRL + C打破会让你的终端破损.这里可能需要更好的错误捕获. (3认同)
  • 最初被认为是最好的解决方案,并在我正在编写的脚本中使用,但 'read -s -p "password: " PASSWORD' 似乎要简单得多。 (2认同)
  • 有关stty的更多信息:http://stackoverflow.com/questions/22832933/what-does-stty-raw-echo-do-on-os-x (2认同)
  • 如果可能,读取似乎可以更好地隐藏密码。`echo -n“密码:” &&读-s密码|| {stty -echo; 读取密码;时髦的回声 }` (2认同)
  • @AndreyKaipov 所以一个最小的 POSIX 兼容密码脚本看起来像这样(假设我不能在注释中添加换行符): `printf "Password: "; trap 'stty echo' INT 退出;stty-回声;读取密码;printf "\n"` (2认同)
  • @BalRog 是的,我觉得没问题!原始片段也是 POSIX。我只是提到陷阱的事情以防万一有人也遇到这种边缘情况。 (2认同)
  • @AndreyKaipov 多年来遇到了太多的脚本,导致 shell 在摆弄“stty”后表现出奇怪的行为,我很高兴看到你的评论,并提醒我可以使用“trap”作为故障保护。 (2认同)

sme*_*ola 82

一个班轮:

read -s -p "Password: " password
Run Code Online (Sandbox Code Playgroud)

在Linux(和cygwin)下,这个表单适用于bash和sh.但它可能不是标准的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 ...]
Read a line from the standard input and split it into fields.
  ...
  -p prompt output the string PROMPT without a trailing newline before
            attempting to read
  ...
  -s                do not echo input coming from a terminal
Run Code Online (Sandbox Code Playgroud)

  • @shao.lo 不,这只是意味着你需要使用 bash,而不是 sh。仅当脚本中的 shebang 标头使用 bash 时,您的评论才适用。 (4认同)
  • 如果命令生成“ read:Illegal option -s”,则表示该脚本需要直接执行(./script与sh ./script)...请参见http://stackoverflow.com/questions/30554353/linux-illegal选项读 (3认同)
  • Linux 中的“sh”一般没有明确定义,每个发行版可以做出自己的选择。假设“bash”是 bash 本身或与 bash 兼容的 shell 是合理的,但“sh”不需要是 bash 甚至与 bash 兼容,并且可能是例如 dash,它不支持“read -s”。 (2认同)

Sus*_*Pal 53

-s的选项read没有在POSIX标准定义.请参见http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html.我想要一些适用于任何POSIX shell的东西,所以我写了一个stty用来禁用echo 的小函数.

#!/bin/sh

# Read secret string
read_secret()
{
    # Disable echo.
    stty -echo

    # Set up trap to ensure echo is enabled before exiting if the script
    # is terminated while echo is disabled.
    trap 'stty echo' EXIT

    # Read secret.
    read "$@"

    # Enable echo.
    stty echo
    trap - EXIT

    # Print a newline because the newline entered by the user after
    # entering the passcode is not echoed. This ensures that the
    # next line of output begins at a new line.
    echo
}
Run Code Online (Sandbox Code Playgroud)

此函数的行为与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
Run Code Online (Sandbox Code Playgroud)

这是另一个使用-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
Run Code Online (Sandbox Code Playgroud)

最后,这是一个示例,说明如何使用该read_secret函数以符合POSIX的方式读取密码.

printf "Password: "
read_secret password
# Do something with $password here ...
Run Code Online (Sandbox Code Playgroud)

  • 应该确保在shell中尚未禁用echo并且如果之前没有启用它...可以使用`oldtty = stty -g`然后在结尾`stty $ oldtty`来恢复之前的设置.否则,它很棒. (8认同)

Man*_*uel 11

我发现这个askpass命令很有用

password=$(/lib/cryptsetup/askpass "Give a password")
Run Code Online (Sandbox Code Playgroud)

每个输入字符都替换为*.请参阅:提供密码****

  • 这个`/lib/cryptsetup/askpass` 来自哪里?它当然不是标准的 *nix(或 GNU/Linux)工具。 (3认同)

Pas*_*don 9

您还可以通过执行以下操作来提示输入密码,而无需在当前 shell 中设置变量:

$(read -s;echo $REPLY)
Run Code Online (Sandbox Code Playgroud)

例如:

my-command --set password=$(read -sp "Password: ";echo $REPLY)
Run Code Online (Sandbox Code Playgroud)

您可以使用换行符添加其中几个提示值,执行以下操作:

my-command --set user=$(read -sp "`echo $'\n '`User: ";echo $REPLY) --set password=$(read -sp "`echo $'\n '`Password: ";echo $REPLY)
Run Code Online (Sandbox Code Playgroud)


Ign*_*ams 6

echo使用 关闭stty,然后再次打开。


oᴉɹ*_*ǝɥɔ 6

linux虽然已经有很多答案,但实际上在任何运行的现代系统中,还有另一种方法可以从终端询问密码systemd(是的,嘘,我知道,但你能做什么呢)。systemd-ask-password命令包含在标准核心systemd包中,可以像这样使用:

#!/bin/sh
PASSWORD="$(systemd-ask-password "Enter your password:")"
Run Code Online (Sandbox Code Playgroud)

使用--emoji=noswitch 来抑制那个愚蠢的 unicode 锁定字符。它在终端内工作得很好,但如果您需要它弹出 GUI 对话框,则需要进行调整,但这超出了此处的范围。