DEV Community

Cover image for Shell script to monitor network on MacOS
kurab
kurab

Posted on

Shell script to monitor network on MacOS

TL;DR

In the context of a global pandemic, more and more people are working from home. In software development, it can be important to know which network to access from, or network speed for a comfortable video conference. It's useful to have a quick check on such things.

I'd like to be able to look up

  • Outgoing IP Address
  • Internal IP Address
  • The Wi-Fi SSID
  • Network Speed DL/UL

with bash script.
And I'd like to display it on the desktop with Geektool, which may not be used by many people these days.
If you just want to see the results, skip all of them and go to github.

kurab/networkMonitorMac

Environments

  • Mac Pro (late 2013) / macOS Catalina version 10.15.7
  • MacBook Air 2020 / macOS Catalina version 10.15.7

Outgoing IP Address

When connecting to a protected network based on a reliable, fixed IP address, it's important to know your external IP address.

You can get it with following command.

$ curl --silent api.ipify.org --max-time 5
Enter fullscreen mode Exit fullscreen mode

So, the script will be like this:

#!/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
Enter fullscreen mode Exit fullscreen mode

"wait" may not be necessary, but we'll put it in from the beginning later, as there's heavy processing involved.

Internal IP Address

First, find out the MAC address of your Wi-Fi adapter.

Go to Preferences > Network and select Wi-Fi, click Advanced to display Hardware and remember the MAC Address. Just remember the last two letters or so.

$ ifconfig
Enter fullscreen mode Exit fullscreen mode

When you hit this command, you'll see a list of things, but try looking for sections like en0: en1: en2: ... In the "ether" section, you can see something like the MAC Address, so look for the MAC Address of the Wi-Fi.

In my case, en2 for Mac Pro and en0 for MacBook Air. The explanation continues with en0.

The IP address of the assigned network is written in en0 of ifconfig, so I extract it.

#!/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
Enter fullscreen mode Exit fullscreen mode

SSID

On MacOS, you can learn a lot of things about Wi-Fi by typing the following command, which was the same on pre-Catalina OSes.

$ /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I
Enter fullscreen mode Exit fullscreen mode

The SSID is the information you want to know. You can get various other information as well, so please scatter what you need as needed.

#!/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
Enter fullscreen mode Exit fullscreen mode

Network Speed DL/UL

Use speedtest-cli to measure the network speed.

It's a bit different in function, but either one is fine. This time, I'll use the latter one, pypi's. I'd like to get it with curl and put it in /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/.
Enter fullscreen mode Exit fullscreen mode

versions:

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

If you switch to a Python version, such as 3.9.0, the following will still work.

$ speedtest-cli --simple
Enter fullscreen mode Exit fullscreen mode

You'll see that it takes quite a bit of time to measure. The code we've been using so far will give you instantaneous results of execution, so if it's annoying, you can separate the scripts.

$ speedtest-cli --simple | grep Download | awk '{print $2}'
Enter fullscreen mode Exit fullscreen mode

You can get it like this, but this is not practical because you have to measure twice with DL/UL, which takes a crazy amount of time. Let's use the measurement once and use it well.

#!/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
Enter fullscreen mode Exit fullscreen mode

speedtest-cli spits out a standard error if you're not connected to the network. I discarded it. "Mbps" is fixed. We'll think about it again when the network is much faster.

LAN cable?!

There may be a case that you are not using Wi-Fi but LAN cable to connect to the Internet. The way to check the network interface is the same. This time, en0 in Mac Pro and MacBook Air do not have the interface of LAN cable, but it is possible to use it via the adapter of USB-C. In that case, it was en2.

In the explanation.

  • Wi-Fi: en0
  • LAN: en2

In the case of a LAN, set only the IP address in the network.

#!/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
Enter fullscreen mode Exit fullscreen mode

Final Source Code

Put all of the above together and adjust the spaces and so on, the source code will look like this

#!/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
Enter fullscreen mode Exit fullscreen mode

executed result is like this

$ ./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
Enter fullscreen mode Exit fullscreen mode

Configure Geektool

Refresh for 120 seconds, time out for 60 seconds, set Font to Ricty and run this bash script, oh my goodness! On my desktop, at all times!

Network Monitoring on Desktop

The network speed isn't very nice tho...

Top comments (0)