その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

雑に特定のホストの特定のポートと疎通できてるかどうか確かめる

新しくサーバ立てた時やサーバ追加した時に,そのサーバが他のホストの特定のポートと疎通できるかどうかチェックする必要が出てくる時がある.ACLとかの兼ね合い.
そういうのは本番の環境だと監視のシステム等に組み込まれていたり,あるいはserverspecとかで確認されていることが多いと思うのだけれど,その場で雑に確認したくなることがあると思う.そういう時はtelnetで繋いで,quitして,というのを繰り返していく感じになりがちなのだけれど,対象となるホストの数が多くなってくるとそういうことを手でやるのも大変になってくる……というわけでこれです.

$ (sleep 0.1; echo quit) | telnet $HOST $PORT)

こういう風にしておくとtelnetで繋いだ後にquitを発行するということを自動でやってくれる.
とはいうものの,こうすると正しく繋げているかどうかを目視で確認する必要が出てくる (つまり以下の様な文字列が正しく出力されているかどうかを目視で確かめる必要がある).

Trying ::1...
Connected to localhost.
Escape character is '^]'.

更にこの方法だと Connection closed by foreign host となるために,exit codeが1となってしまう.その為,スクリプト中でexit codeを使って良い感じにするのが難しい.


というような話をしていたら,id:karupaneruraさんから「それncで出来るよ」と教えてもらって以下の様な感じになった.

if [ -z $((sleep 0.1; echo "\nquit") | nc $HOST $PORT) ]; then
    echo "Fail $HOST:$PORT"
fi

見た目としてはtelnetの代わりにncを使って,送り込む文字列を quit から \ncode にしたという様子.
前者はまあその通りという感じ.後者について少し説明すると,ncで正しく繋げている場合に先に改行文字を送り込むと ERROR というレスポンスがncから返ってきた後にquitする.一方で正しく繋げていない場合はncから何もレスポンスが返ってこないという挙動になるので,それを利用して文字列が空か空ではないかで正しく繋げているか否かを判断している (つまり文字列が空でなければ正しく繋げていると判断している).

なお補足すると,ncだとこういう風に動くんだけど,CentOS6のncatコマンドだとquit時に+OKという文字列が出てくるので最初に改行文字を送り込む必要は無かったりする.みたいな感じで微妙にnc (ncat) コマンドの挙動に差があったりするので,そこら辺はまあ臨機応変に対応しましょうという感じ.


これを適当にforの中に組み込んでおくと雑に疎通のチェックが出来て便利,という話でした.ncを使うという発想がなかったので勉強になった.


[追記]

コメントでid:bearminiさんが /dev/tcp を使う方法を教えてくれたんですが,これめちゃめちゃ便利ですね.知らなかった……