Bash

如何使用 bash“正確”讀取遠端 sshd 伺服器版本

  • August 1, 2022

我正在嘗試在不安裝額外工具的情況下使用 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字元?

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對於 Internet 協議,該序列通常是強制性的,並且與典型的 Unix\n換行符序列不同,但這是一個不同的問題……但這就是那個討厭\r的問題存在的原因。)

引用自:https://unix.stackexchange.com/questions/712040