如何使用 bash“正确”读取远程 sshd 服务器版本

如何使用 bash“正确”读取远程 sshd 服务器版本

我正在尝试使用 bash 读取远程 SSHD 服务器版本,而无需安装额外的工具:

$ cat < /dev/tcp/x.y.z.t/22
SSH-2.0-OpenSSH_7.2 FreeBSD-20160310
^C

需要 CTRL+C,所以我尝试只读取一行,但输出中发生了一些奇怪的事情:

$ read version < /dev/tcp/x.y.z.t/22
$ echo "=> version = $version, DONE."
, DONE.ion = SSH-2.0-OpenSSH_7.2 FreeBSD-20160310

我刚刚发现变量值\r末尾有一个字符version

$ printf "$version" | od -ct x1z
0000000   S   S   H   -   2   .   0   -   O   p   e   n   S   S   H   _
         53  53  48  2d  32  2e  30  2d  4f  70  65  6e  53  53  48  5f  >SSH-2.0-OpenSSH_<
0000020   7   .   2       F   r   e   e   B   S   D   -   2   0   1   6
         37  2e  32  20  46  72  65  65  42  53  44  2d  32  30  31  36  >7.2 FreeBSD-2016<
0000040   0   3   1   0  \r
         30  33  31  30  0d                                              >0310.<
0000045

如何防止 bashread内置函数读取尾随\r字符?

答案1

IFS变量可以(本地!)修改为也包含\r.该代码可能需要对参数进行更多错误检查,并且可能需要对如何处理超时或其他此类网络问题进行一些思考。

function read-ssh-version {
   local IFS=$'\r\n'
   read version < /dev/tcp/"$1"/"$2"
   echo "$version"
}

一些最小的临时测试,以确保该函数有效并且全局IFS变量尚未被修改:

bash-5.1$ read-ssh-version 127.0.0.1 22 | od -c
0000000    S   S   H   -   2   .   0   -   O   p   e   n   S   S   H   _
0000020    9   .   0  \n
0000024
bash-5.1$ echo -n "$IFS" | od -c
0000000       \t  \n
0000003

(该\r\n序列对于互联网协议来说通常是强制性的,并且与典型的 Unix 换行序列不同\n,但这是一个不同的问题......但这就是为什么那个讨厌的东西\r在那里。)

相关内容