我的理解是,如果我在xterm中键入以下命令:
$ ssh ir@localhost
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
ir@localhost's password:
然后ssh
进程的stdin和stdout都连接到pty。因此,当我输入密码时,ssh
只是从标准输入中读取密码。
但是我的心理模型无法解释这一点:
$ yes | ssh ir@localhost
Pseudo-terminal will not be allocated because stdin is not a terminal.
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
ir@localhost's password:
...
...
zsh: command not found: y
...
在这里,yes
的stdin连接到pty,并且yes
的stdout通过管道传递到ssh
的stdin。因此ssh
应该冒y
s的泛滥,但它足够聪明地告诉它,其stdin不是tty,并且stdin的内容不应解释为密码。相反,y
被缓冲,并且登录成功后,它们将直接传送到远程端的bash进程。
但是ssh怎样才能获得我键入的密码? pty将我的密码发送到yes
,然后将其丢在地板上。
此外,ssh
声称不分配pty的说法似乎是谎言。以下代码片段显示了stdin是否为tty:
$ [ -t 0 ] && echo true || echo false;
true
当我将此命令传递给ssh时,它最初会按预期打印出“ false”:
$ echo "[ -t 0 ] && echo true || echo false;" | ssh ir@localhost
Pseudo-terminal will not be allocated because stdin is not a terminal.
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
ir@localhost's password:
...
false
$ [ -t 0 ] && echo true || echo false;
true
但是当我在远程shell上运行相同的命令时,它会打印出“ true”。我什至可以打开vim
,并在调整本地终端的大小时,vim
调整其适当显示的文本的大小。仅当ssh
客户端通过网络发送有关调整大小的信息,并且sshd
通知vim
流程(就像pty一样)时,才有可能。
有趣的是,当我按Ctrl + C时,ssh
会话立即终止。我对此的解释是,pty拦截Ctrl + C并将SIGINT发送到yes
和ssh
。如果ssh
分配了一个pty,它将截获信号并将其通过电线传输到远程主机,并且远程运行的任何进程都会被中断。但是由于ssh
没分配
pty,它就死了。因此,这部分是可以预期的...但是我仍然不明白为什么[ -t 0 ]
在远程shell上传递,以及ssh
如何能够通过yes
读取密码它。