/dev/tty 和 stdin 的一个不同
尝试给 ssh 写一个 ProxyCommand1 的实现的过程中发现:
- 如果是使用
ssh -W,它可以顺利从终端中读取密码; - 如果是我自己的程序,则只能读取到主 ssh 发来的“版本号”。
我百思不得其解,不知问题在哪。 实际例子如下:
1 2 |
|
换成我自己的测试程序(从标准输入读取密码):
1 2 3 4 5 6 7 8 9 10 11 |
|
编译成 ./test 后尝试执行一下:
1 2 3 |
|
有点儿意外,但是读了上面 ProxyCommand 的原理文章后,又觉得没有那么奇怪:
启用 ProxyCommand 后,主 ssh 进程确实是通过 stdin/stdout 和 ProxyCommand 通信的,所以读取到版本号字符串理所当然。
翻源代码
但是 ssh -W 是怎么绕过标准输入并从终端读取到密码的呢?
然后我跑去看了一下 openssh 的源代码有没有对此种情形的 ssh 进行特殊处理,答案是:没有。
但是,在读密码函数处发现“奇怪”的地方,它读 /dev/tty 了:
75 76 77 78 79 80 81 82 83 84 85 86 87 |
|
答案揭晓:先读 /dev/tty,不成功才读 stdin。
至于 /dev/tty 是个什么东西?简单答约:当前进程的控制终端(键盘?),不管 stdin/stdout 有没有被重定向。
一些结论
| 输入来源 | 能否获取到终端用户的输入 | 举例 |
|---|---|---|
os.Stdin |
❌ 不一定,因为可能被重定向 | 被 SSH 主进程用作数据通道以交换数据 |
/dev/tty |
✅ 一定连接到终端/键盘输入 | 不管标准输入是否被重定向,都能读取 |