我想将 ssh 的输出通过管道传输到不同的命令。例如:
ssh myserver cat remote-file | diff local-file -
Run Code Online (Sandbox Code Playgroud)
问题是我的服务器要求输入密码,但我无法输入。(出于某种原因,服务器上不提供公钥身份验证。我无法更改这一点。)我收到“密码:”提示,但我键入的密钥被回显,并且没有传递给 ssh。如何让 ssh 获取密码?
注意我不是试图将密码通过管道传输到 ssh。我正在尝试通过管道传输 ssh 的输出,并像往常一样输入密码。
以防万一,我在 OS X 10.7 (Lion) 和标准终端上使用 bash。我没有设置可能导致这种情况的别名。我在不同的(Linux)系统上看到了同样的问题,所以我相信这不是我的设置所特有的。
好吧,事实证明这是由于与我的 bash 配置的奇怪交互造成的。
我有一些东西.bash_profile可以将当前执行的命令放入窗口标题或screen选项卡中。它的工作原理是使用trap:
trap 'bash_current_command' DEBUG
Run Code Online (Sandbox Code Playgroud)
在此之前:
function bash_current_command {
# only works in bash > 3.1
#set -- $BASH_COMMAND
# for old bash
set -- $(history 1)
shift
if [[ "$1" == "sudo" ]]; then
cmd="*$(basename -- "$2")*"
else
cmd="$(basename -- "$1")"
fi
bash_set_title "$cmd"
}
Run Code Online (Sandbox Code Playgroud)
bash_set_title是一个使用 ANSI 转义码设置当前终端标题和图标标题的小函数。正如您所看到的,这会创建 subshells $(...),我的直觉告诉我这可能是问题所在。事实上,在我改变这些行之后,它起作用了!
如果有人知道为什么会发生这种情况,我很高兴听到详细信息。子 shell 通常会窃取tty输入吗?或者这只是调试陷阱中的问题?我不记得常规stdin输入/管道命令的问题。
(正如您还可以看到的,我的函数无论如何都存在一些问题 - 它使用其中一个子 shell 作为解决方法,因此它可以在古老的 bash 版本上运行(我在遗留系统上坚持使用它,但仍然想要一个统一的配置)。另一个子shell用于在使用时提取实际命令sudo,但是如果使用像这样的开关调用sudo,则会失败sudo -H -u user command。所以我将这视为修复此代码的机会...)