non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

goroutineを使って高速にLAN内の*.localなホスト名の一覧を取得するツールを作った

こんばんは。次男が週末に初の保育園のお泊り会がある@kjunichiです。

背景

DHCPでLANに繋げる環境であれば、 raspberry piなどえはraspberrypi.localというホスト名でsshできたり、macOSなどでも ホスト名.localで手軽にアクセスできるため、/etc/hostsすら編集しなくても便利にリモートPC等に アクセスできる。

しかし、このホスト名が何か分からない場合、少なくともmacOSdns-sdコマンドではDNSの逆引きに 相当することが出来ず、数年間途方に暮れていた。。avahiはこれが出来るのを知っていた。

SOで以下のページを発見するも、最近までdigコマンドに結構なスターがついている意味が まるで分らなかった。

serverfault.com

最近になって、このdigコマンドが、21世紀のnslookupでmDNSにも対応しているので、 これでmacOSでもdigコマンドでホスト名.localをIPアドレスから逆引きできることが分かった。

IPアドレスから逆引きしてホスト名.localな名前を引くことが出来ることが分かったので、 LAN内のIPアドレスを片っ端から引数に指定して結果を表示すれば、やりたかった LAN内に現在どんなホスト名.localが存在しているのかコマンドができる。

コマンドラインで存在しないIPアドレスを指定して以下の様にdigコマンドを実行すると

dig +short -x 192.168.0.9 @224.0.0.251 -p 5353

かなり、待たされる。

ということで、Goでgoroutine使って、並行にコマンドを実行すれば良いのでは? ということを思いついた。

Goで外部プロセスの実行結果を取得する処理は「Raspberry Piの温度をgRPCを使ってElectronで作ったデスクトップマスコットに表示させた」の記事で習得済み。

学べたこと

同時に実行するコマンド数を絞りつつ、複数同時に実行する

さすがに、digコマンドに渡す引数のIPアドレスをクラスCで1から254まで指定してそれを同時に実行するのは ちょっとOSに優しくないだろうということで、同実行数を絞りつつ実行する方法を 探した。

mattn.kaoriya.net

今回のコードの大枠はこちらのコードをベースにさせてもらった。

for内でgoroutineを実行する際にやりがちなミスを学習

qiita.com

goroutineに渡しているループ変数は、ループされる度に作られる変数ではなく、 ループ全体で使われる変数

ただし、上の例だと文字列のアドレスを渡すことになるから この問題は発生しないのかも?と思いもしたが、Sleep消したら駄目だった。。。

ちなみに、この問題、VS Codeのおかげで早期に発見できた。

#golang vs codeのこの警告のおかげでサッサと問題解決出来た。

Junichi Kajiwaraさん(@kjunichi)がシェアした投稿 -

sprintf的なものがある

qiita.com

テンプレートの仕組みも見つけるも、ちょっと大げさだったので、 Cのsprintf的なものも見つけたので、今回はこちらを採用した。

成果物

こうして、今回も実際に自分の手を動かして取り組んだところ、多くの学びがあった。

github.com

今後の課題

あらたな使い道

iPhoneWifi接続になっていると、dareka-no-iPhone.localなどと一覧に表示さるので、自宅に自分や奥さんがいるかをコマンドラインでチェック可能になった

参考資料

今回はavahiのないmacOSで逆引きする方法としてdigコマンドを用いて行ったが、Windowsでもdigコマンドを インストールすることが以下の記事によると出来るようなので、たぶんWindowsでも動くのでは。

www.atmarkit.co.jp

関連記事

12年前の記事

6年前の記事