在符合 POSIX 的 shell 中询问密码?

Hey*_*Hey 19 shell scripting password posix

当我想在bash脚本中要求输入密码时,我会这样做:

read -s
Run Code Online (Sandbox Code Playgroud)

...但是当我bash在 POSIX 模式下运行时sh,该-s选项被拒绝:

$ read -s
sh: 1: read: Illegal option -s
Run Code Online (Sandbox Code Playgroud)

如何使用符合 POSIX 的命令安全地请求输入?

Sté*_*las 25

read_password() {
  REPLY="$(
    # always read from the tty even when redirected:
    exec < /dev/tty || exit # || exit only needed for bash

    # save current tty settings:
    tty_settings=$(stty -g) || exit

    # schedule restore of the settings on exit of that subshell
    # or on receiving SIGINT or SIGTERM:
    trap 'stty "$tty_settings"' EXIT INT TERM

    # disable terminal local echo
    stty -echo || exit

    # prompt on tty
    printf "Password: " > /dev/tty

    # read password as one line, record exit status
    IFS= read -r password; ret=$?

    # display a newline to visually acknowledge the entered password
    echo > /dev/tty

    # return the password for $REPLY
    printf '%s\n' "$password"
    exit "$ret"
  )"
}
Run Code Online (Sandbox Code Playgroud)

请注意,对于那些printf未内置的shell (mksh) ,密码将在ps输出中以明文形式显示(几微秒),或者如果所有带有参数的命令调用都被审计,则密码可能会显示在某些审计日志中。

  • `cat` + heredoc 可能比 `printf` 更安全吗? (2认同)
  • @hildred,请注意 [`REPLY="$(...)"` 中的引号不会造成伤害(SE 语法突出显示除外)但不是必需的](http://unix.stackexchange.com/a /220386) (2认同)

ser*_*sat 23

read -s不在 POSIX 中。如果您想符合 POSIX 标准,请使用stty -echo. sttyecho参数在 POSIX 中定义。

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

这将适用于所有符合 POSIX 的 shell。

来源

  • 为了突出@arkadiusz-drabczyk 评论中的答案中的一点,最好捕获所有可以捕获的信号以重新打开“stty echo”——以防用户感到困惑并点击控制—— C 在“读取密码”部分。 (7认同)
  • 您不应该无条件地打开回显,您应该保存并恢复旧的设置。许多人在 Emacs shell 缓冲区中工作,这通常会禁用回显,因为 Emacs 本身会进行回显。另一个答案展示了如何做到这一点。 (2认同)