将 ssh 输出传送到其他命令时使用键盘交互式身份验证

jdm*_*jdm 7 bash ssh pipe

我想将 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)系统上看到了同样的问题,所以我相信这不是我的设置所特有的。

jdm*_*jdm 4

好吧,事实证明这是由于与我的 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 转义码设置当前终端标题和图标标题的小函数。正如您所看到的,这会创建 subshel​​ls $(...),我的直觉告诉我这可能是问题所在。事实上,在我改变这些行之后,它起作用了!

如果有人知道为什么会发生这种情况,我很高兴听到详细信息。子 shell 通常会窃取tty输入吗?或者这只是调试陷阱中的问题?我不记得常规stdin输入/管道命令的问题。

(正如您还可以看到的,我的函数无论如何都存在一些问题 - 它使用其中一个子 shell 作为解决方法,因此它可以在古老的 bash 版本上运行(我在遗留系统上坚持使用它,但仍然想要一个统一的配置)。另一个子shell用于在使用时提取实际命令sudo,但是如果使用像这样的开关调用sudo,则会失败sudo -H -u user command。所以我将这视为修复此代码的机会...)