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

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

我想将 ssh 的输出通过管道传输到另一个命令。例如:

ssh myserver cat remote-file | diff local-file -

问题是 myserver 要求输入密码,但我无法输入。 (由于某种原因,公钥身份验证在服务器上不可用。我无法更改此设置。)我收到“密码:”提示,但我键入的密钥会回显,并且不会传递到 ssh。如何让ssh获取密码?

请注意,我并不想将密码通过管道传输到 ssh。我正在尝试通过管道传输 ssh 的输出,并像往常一样输入密码。

以防万一,我在 OS X 10.7 (Lion) 上使用 bash 和标准终端。我没有设置可能导致此问题的别名。我在不同的(Linux)系统上看到过同样的问题,所以我相信这不是我的设置所特有的。

答案1

好吧,事实证明这是由于与我的 bash 配置的奇怪交互造成的。

我有一些东西.bash_profile可以将当前执行的命令放入窗口标题或screen选项卡中。它的工作原理是使用trap

trap 'bash_current_command' DEBUG

在此之前:

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"
}

bash_set_title是一个使用 ANSI 转义码设置当前终端标题和图标标题的小函数。正如您所看到的,这会创建 subshel​​ls $(...),我的直觉告诉我这可能是问题所在。事实上,在我改变这些行之后,它起作用了!

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

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

答案2

此答案并未解释您的具体问题,但提供了一些可能的解决方法,这些解决方法也可能使您的生活更加方便。

如果您仅使用 ssh 访问远程文件而不运行远程命令,那么您可以通过以下方式挂载远程文件系统sshfs。你需要安装OS X 的保险丝SSHFS第一的。 (我不知道是否有 OSX 的二进制发行版。)然后运行

mkdir ~/myserver
sshfs myserver:/ ~/myserver

仅当运行该命令时才需要进行身份验证sshfs。之后,远程文件就可以在 下使用~/myserver,因此您可以diff ~/myserver/path/to/remote-file local-file不必担心其中一个文件是远程的。运行fusermount -u ~/myserver以卸载文件系统。

另一种允许您进行一次身份验证然后运行许多 ssh 命令的方法是设置主连接。看重复使用 ssh 会话来执行 rsync 命令

相关内容