Bash:如何在不通过 SSH 回显的情况下从标准输入读取密码

Bash: How to read password from stdin without echoing over SSH

我有以下有效的脚本:

echo -n "Enter sudo password: "
read -s sudo_pass
echo "$sudo_pass" | ssh -tt myhost "sudo -S ./remote_script.sh"

问题出在输出上。我希望 stdin 的密码供 sudo 使用,但不要打印到屏幕上。相反,我得到:

<system banner>

thepassw0rd
[sudo] password for theuser:

有没有办法做到这一点?我什至不确定哪个命令导致输入被打印出来。

更新

我发现 ssh 正在打印输入:

echo 123 | ssh -tt myhost "sleep 2"

这给了我

<system banner>

123
Connection to myhost closed.

这里的问题在于 ssh-tt 选项。你强迫它分配一个伪终端。这个伪终端读取标准输入,但不知道它读取的内容是来自您的键盘还是重定向 (echo "$sudo_pass" | ssh ...)。所以它就像一个终端并回显它接收到的内容(因为它在 sudo 有时间 运行 并捕获标准输入之前接收到它)。

您遇到了 -t 选项的缺点之一。另一个还没有打到你的是,如果你的密码以 ssh 转义序列(~C~? 等)开头,这也不会按预期工作。

简单且最佳的解决方案:不要使用 -tt 选项。

如果你真的离不开它 - 因为例如你的远程脚本坚决想要一个终端 - 一个(丑陋的)解决方案是“吃掉”ssh 发回的第一行,因为你肯定知道回显的永远是你的密码:

echo "$sudo_pass" | ssh -tt myhost ... | ( read; cat )

就个人而言,我不太确定第一行总是密码,我不推荐这样做。一个更好的选择是在发送密码之前添加一个小延迟,以便让 sudo 远程启动并捕获标准输入:

( sleep 1; echo "$sudo_pass" ) | ssh -tt myhost ...

但这仍然是一个 hack,最好的解决方案当然是不使用 ssh-tt 选项。