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が必要なので、1行だけ読み取ろうとしましたが、出力で奇妙なことが発生しました。

$ 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

readbash組み込み機能が末尾の文字を読み取らないようにする方法は\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存在する理由です。)

関連情報