Bash:如何在SSH连接中从标准输入读取密码而不回显

3

我有以下脚本,它可以正常工作:

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.

1
@chepner,我在脚本的开头。为了简洁起见,这个脚本已经被大幅简化了。最后一行实际上是循环遍历许多具有相同sudo密码的服务器的一部分,而我只想提示我的用户一次。 - Andy
1
您应该考虑配置 sudo,以允许一个适当的用户在不需要密码的情况下运行该命令。 - chepner
2
你是否使用了 -tt 是因为 remote_script.sh 需要一个伪终端,还是因为你认为 sudo 需要? - chepner
2
如果我完全诚实地回答,我会说:“因为互联网上这么说。”在看到你的评论之前,我尝试了-T,然后它起作用了。谢谢! - Andy
1
“-T” 可能不是必要的;它是默认设置,并且可能用于覆盖(例如)SSH配置文件中的设置。 - chepner
显示剩余2条评论
1个回答

3
这里的问题出在 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 选项。


2
值得注意的是,sudo-S 标志仍然是必需的,只需要删除 ssh-tt 标志即可。 - Shane Bishop
完全正确,@Shane,这是一个通用的答案。正如OP在他的问题中所示,该问题与sudo无关。顺便说一句,感谢您的编辑。 - xhienne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接