我正在尝试使用 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
在那里。)