将远程文件输入 diff 时出现密码问题

将远程文件输入 diff 时出现密码问题

当我想将本地文件与远程文件进行比较时,以下任何一个通常都可以工作:

$ ssh remote cat file | diff file -
$ diff file <(ssh remote cat file)

但是,有时(特别是需要密码时)它们会失败,如下所示:

$ ssh remote cat file | diff file -
1,162d0
< ...
< ...
Password: 

这里,diff不等待ssh完成并认为第二个文件为空。直到diff完成后才ssh要求输入密码,但为时已晚。

$ diff file <(ssh remote cat file)
Password: 
Password:       # asking again after a few seconds
#&%Pasword:     # the typed raw password leaks into the terminal
user@remote's password:
Permission denied, please try again.
user@remote's password:
Permission denied, please try again.
user@remote's password:
Received disconnect from XXX.XX.XX.XX: 2: Too many authentication failures for user
1,162d0
< ...
< ...

这次,ssh要求输入密码,但输入的密码会回显到终端,但ssh无法获取。最后,ssh失败并diff继续使用空的第二个文件。

您能否解释一下为什么会发生这些情况,或者详细说明发生了什么在引擎盖下

答案1

当您首先运行 ssh 时:

ssh remote 'cat file' | cat

ssh 将您的控制终端作为标准输入,因此您可以毫无问题地输入密码。

当你使用 bash 时流程替代,stdin 保持连接到第一个命令,并且子进程的输出管道作为参数传递给第一个命令:

cat <(ssh remote 'cat file')

如果 ssh 协商成功,/dev/fd/63将是一个包含 输出的管道ssh remote 'cat file'

这可以通过以下命令进行演示:

$ echo <(ls)
/dev/fd/63

其中重要的部分是您的终端连接到 的catstdin,而不是ssh。当它运行时,cat会得到一个命令行参数,例如/dev/fd/63.因此,cat 完全忽略 stdin;但是,它仍然连接到 cat 进程,而不是ssh,因此您的密码无处可去。

如果您想更改此设置,则需要ssh先运行,并将输出通过管道传输到diff,如上面所示:

ssh remote 'cat file' | diff file -

相关内容