Macでネットワーク接続状況をモニタリングするシェルスクリプト

## はじめに
受託開発をやっていてどのネットワークからアクセスするかが重要だったり、ネットワークの遅い国で仕事をしていたり、自宅のネットワークが不安定だったり、なにかとネットワーク接続状況が気になる仕事柄、そんなようなことがすぐに確認できると便利です。

という訳で、

- 外に出ていく IP Address
- ネットワーク内の IP address
- 接続している Wi-Fi
- ネットワーク速度 DL/UL

が調べられるようにしたいと思います。最終的には、最近は使ってる人はあんまりいないのかも知れない Geektool でデスクトップに表示しておきたいと思います。

結果だけ知りたい人は、全部飛ばして完成品または、[github](https://github.com/kurab/networkMonitorMac) へどうぞ。

## 実行環境

- Mac Pro (late 2013)
- macOS Catalina version 10.15.7

と

- MacBook Air 2020
- macOS Catalina version 10.15.7

です。

## 外に出ていく IP Address

会社の場合は、固定のことがほとんどだと思います。固定の IP Address を使って、いわゆる境界防御モデルによって保護されたネットワークにアクセスしたりします。開発環境の Web サーバには、社内からアクセスできない。みたいなのは、これですね。
テレワーク時代には、合わないネットワーク・セキュリティで、今後見直す会社が増えそうです。

本記事とは関係ありませんが、Global な大企業では、驚くほどノーガードなことがよくあります。まぁそんなもんなのかも知れません。

では、まず外部に出ていく際に利用している IP Address の調べ方ですが、

```
$ curl --silent api.ipify.org --max-time 5
```
これで取れます。なので、

```bash
#!/bin/bash
ext_info=`curl --silent api.ipify.org --max-time 5`

wait

if [ -n "$ext_info" ];
then
    echo "External: $ext_info"
else
    echo "External: OFFLINE"
fi

unset ext_info
```

wait はなくても良いかも知れませんが、後ほど重い処理があるので最初から入れておくことにします。

## ネットワーク内のIP Address

まず、Wi-Fi アダプターの MAC アドレスを調べます。

環境設定＞ネットワーク で Wi-Fi を選択し、Advanced をクリックし Hardware を表示すると、MAC Address が書いてあるので、それを覚えておきます。最後の2文字くらい覚えておけば良いです。

続いて、ifconfig します。

```
$ ifconfig
```

このコマンドを打つと、ズラーッと色々なものが表示されるのですが、en0: en1: en2: ... というようなセクションを探してみてください。その中の ether という項目に、先程の MAC Address っぽいものが書かれているので、さっきの Wi-Fi の MAC Address が書かれているものを探してください。

私の場合、Mac Pro では en2、MacBook Air では en0 でした。以降 en0 で説明を続けます。

割り当てられているネットワーク内の IP Address は、ifconfig の en0 に書かれているので、抜き出します。

```
$ ifconfig en0 | grep inet | grep netmask | grep -v 127.0.0.1 | awk '{print $2}'
```

bash script は、

```bash
#!/bin/bash
en0_info=`ifconfig en0 | grep inet | grep netmask | grep -v 127.0.0.1 | awk '{print $2}'`

wait

if [ -n "$en0_info" ];
then
    echo "Wi-Fi: $en0_info"
else
    echo "Wi-Fi: INACTIVE"
fi

unset en0_info
```

## 接続している Wi-Fi の情報

我が家には Wi-Fi Router と Bridge があり、接続する場所が1階なのか2階なのかによって接続すべきスポットが異なります。どっちを掴んでるかを知りたい。
また、オフィスでは、Wi-Fi の場合は、スポットによってネットワークセグメントが違って…という境界防御モデルセキュリティになっていることもあるかと思いますので、どこに接続しているかは簡単に分かった方が良い。

MacOS の場合、以下のコマンドを打つことで、Wi-Fi の色々が分かります。Catalina 以前の OS でも同じだったので、Catalina 以外でも使えると思います。

```
$ /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I
```

このコマンドを打って出てくる、SSID が知りたい情報です。他にも色々な情報が取得できるので、必要なものを適宜散りばめてください。私の場合は、SSID だけで良いので、以下のコマンドで抜き出します。

```
$ /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | awk -F: '/ SSID: / {print $2}' | sed -e 's/.*SSID: //'
```

bash script は、

```bash
#!/bin/bash
en0_info=`ifconfig en0 | grep inet | grep netmask | grep -v 127.0.0.1 | awk '{print $2}'`

wait

if [ -n "$en0_info" ];
then
    wifi_network=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | awk -F: '/ SSID: / {print $2}' | sed -e 's/.*SSID: //'`


    echo "Wi-Fi: $en0_info"
    echo "- SSID: $wifi_network"

    unset wifi_network
else
    echo "Wi-Fi: INACTIVE"
fi

unset en0_info
```

## ネットワーク速度 DL/UL

ネットワーク速度の計測には、speedtest-cli を利用します。

[SPEEDTEST CLI](https://www.speedtest.net/apps/cli)
[speedtest-cli](https://pypi.org/project/speedtest-cli/)

ちょっと機能が違いますが、どっちでも良いです。今回は、後者の pypi のものを使います。
pip ではなく、curl で取ってきて、/usr/local/bin にでもぶちこんでおきたいと思います。

```
$ curl -Lo speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
$ chmod +x speedtest-cli
$ mv speedtest-cli /usr/local/bin/.
```

一応、今回入ったバージョン等の情報は、

```
$ speedtest-cli --version
speedtest-cli 2.1.2
Python 3.8.3 (default, Jul  2 2020, 11:26:31) [Clang 10.0.0 ]
```

でした。Python のバージョンを 3.9.0 等に切り替えても、以下の内容はちゃんと動きます。

```
$ speedtest-cli --simple
```

とすると、計測には結構時間がかかるのが分かると思います。これまでのコードは、実行結果が一瞬で出るので、煩わしい場合は、スクリプトを分けてしまっても良いと思います。

```
$ speedtest-cli --simple | grep Download | awk '{print $2}'
```

こんな風にすれば取れますが、これだと、DL/UL で2回計測する必要があり、めちゃくちゃ時間がかかるので、実用的ではありません。計測は1回にして、うまいこと使いましょう。

```bash
#!/bin/bash
speed_info=`/usr/local/bin/speedtest-cli --simple 2>/dev/null | grep load | sed -e 's/^.*: //g;s/ M.*$//g'`

wait

if [ -n "$speed_info" ];
then
    dl_speed=`echo $speed_info | awk '{print $1}'`
    ul_speed=`echo $speed_info | awk '{print $2}'`

    echo "Download: $dl_speed Mbps"
    echo "Upload: $ul_speed Mbps"

    unset speed_info
    unset dl_speed
    unset ul_speed
else
    echo "Download: -"
    echo "Upload: -"
fi
```

ネットワークにつながっていないと speedtest-cli が標準エラーを吐くので、それは捨てました。Mbps は決め打ちです。ネットワークがもっと速くなったらまた考えましょう。

homebrew でインストールする方を利用される場合 --simple オプションがなかったりしますが、基本的には一緒です。よしなに grep, sed してください。


## LAN ケーブルで接続してる場合

Wi-Fi じゃなくて LAN ケーブルでネット接続している場合もあるかも知れないので、一応対応しておきましょう。ネットワーク・インターフェースの調べ方は、ifconfig ゴニョゴニョと、同じです。今回、Mac Pro では、en0, MacBook Air には LANケーブルのインターフェースはないのですが、USB-C のアダプター経由で利用することが可能で、その場合、en2 でした。

説明上は、

- Wi-Fi: en0
- LAN: en2

として進めます。LAN の場合は、ネットワーク内のIP Addressだけにしておきます。

```bash:networkMonitor.sh
#!/bin/bash
en2_info=`ifconfig en2 |grep inet |grep netmask |grep -v 127.0.0.1 |awk '{print $2}'`

wait

if [ -n "$en2_info" ];
then
    echo "Ethernet: $en2_info"
else
    echo "Ethernet: INACTIVE"
fi

unset en2_info
```

余談ですが、USB-C等でくっつける LANアダプターは、セキュリティ的には良くない場合があります。MAC Address というのは、Physical Address とも言い、その名の通り、物理的なものについているアドレスです。LANアダプターの MAC Address は LANアダプター自身についています。なので、別のPCに挿しても、MAC Address は変わりません。なので、MAC Address を元にアクセス制限をしていたり、アクティビティを監視しているような場合、アクセス制限や監査ログ的な意味はなくなって/薄れてしまいます。MAC Address は偽装が簡単な割に、あちこちで使われているので、注意したいところ。


## 完成品

以上、まとめて、スペース等を美しく調整すると、

```bash:networkMonitor.sh
#!/bin/bash
speed_info=`/usr/local/bin/speedtest-cli --simple | grep load | sed -e 's/^.*: //g;s/ M.*$//g'`

ext_info=`curl --silent api.ipify.org --max-time 5`

en0_info=`ifconfig en0 | grep inet | grep netmask | grep -v 127.0.0.1 | awk '{print $2}'`
en2_info=`ifconfig en2 | grep inet | grep netmask | grep -v 127.0.0.1 | awk '{print $2}'`

wait

if [ -n "$speed_info" ];
then
    dl_speed=`echo $speed_info | awk '{print $1}'`
    ul_speed=`echo $speed_info | awk '{print $2}'`

    echo "Download   : $dl_speed Mbps"
    echo "Upload     : $ul_speed Mbps"

    unset speed_info
    unset dl_speed
    unset ul_speed
else
    echo "Download   : -"
    echo "Upload     : -"
fi

echo ""

if [ -n "$ext_info" ];
then
    echo "External   : $ext_info"
else
    echo "External   : OFFLINE"
fi

unset ext_info

if [ -n "$en0_info" ];
then
    wifi_network=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | awk -F: '/ SSID: / {print $2}' | sed -e 's/.*SSID: //'`


    echo "Wi-Fi      : $en0_info"
    echo "- SSID     :$wifi_network"

    unset wifi_network
else
    echo "Wi-Fi      : INACTIVE"
fi

unset en0_info

if [ -n "$en2_info" ];
then
    echo "Ethernet   : $en2_info"
else
    echo "Ethernet   : INACTIVE"
fi

unset en2_info
```

実行結果は、こんな感じ

```
$ ./networkmonitor.sh
Download   : 37.69 Mbps
Upload     : 54.78 Mbps

External   : XXX.XXX.XXX.XXX
Wi-Fi      : 192.168.1.19
- SSID     : XXXXXXXXXXXXXXX
Ethernet   : INACTIVE
```

## Geektool に設定する

120秒リフレッシュ、60秒タイムアウトにして、Font を Ricty にして、このbash script を実行すると、あら素敵！デスクトップ上で、いつでも確認できる！

![IMG_9838.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245908/afca472e-1242-c88c-64b7-39d9e960987e.png)

ネットワークスピードは、あんまり素敵じゃないですね。