Search code examples
bashmacoswifi

Mac script to check if there is any wifi connection


I have searched and am having troubles finding an answer, im sorry if this is a novice question...

I am creating a program to automatically reconnect to my VPN and mount required drives in the event of a disconnect. So far, it works perfect (checks every 60 seconds or so for the VPN)

Problem comes when I am not near wifi, it keeps yelling at me that it cannot connect. Is there a bit of code that exists to simply check if I am connected to the internet before running the rest of the script, and if I am not connected to the internet, to just leave me alone until I reconnect? Most of what I can find looks to ping a website (which im not adverse to doing, especially if i can use it to ping the VPN) but does not seem to work in the background without notifying me that it still cannot see the server.


Solution

  • There a few ways you can verify internet connectivity; the simplest of which is to just ping an external host (one that you expect to be up), then check the status code.

    Replace www.google.com with your.vpn.host or any host you desire in the following examples.

    host="www.google.com"
    
    ping -c1 "$host" &> /dev/null
    
    if [ $? -eq 0 ]; then
      # connection is UP
    else
      # connection is DOWN
    fi
    

    Alternatively, you can use nc to specify a custom port number and connection timeout period:

    # Note: w/ the macOS BSD version of `nc` you use the `-G` flag rather than the `-w` flag to specify the connection timeout.
    
    host="www.google.com"
    port=80
    timeout=5
    
    nc -G$timeout -z "$host" "$port" &> /dev/null
    
    if [ $? -eq 0 ]; then
      # connection is UP
    else
      # connection is DOWN
    fi
    

    If you don't want to rely on external commands, and instead decide you want to leverage bash native TCP sockets (and also specify a custom port number and connection timeout period):

    host="www.google.com"
    port=80
    timeout=5
    
    echo > "/dev/tcp/$host/$port" & pid="$!"
    { sleep "$timeout"; kill "$pid"; } &> /dev/null & 
    wait "$pid" &> /dev/null
    
    if [ $? -eq 0 ]; then
      # connection is UP
    else
      # connection is DOWN
    fi
    

    If you simply want to check if you are connected to a WiFi network on a specific interface (macOS ONLY), you can use:

    # Replace `en0` with the interface you want to check
    networksetup -getairportnetwork en0
    
    # There is no convenient status code check that I am aware of here. You can 
    # save the output to a variable and grep for the word: "off"
    
    # I don't think this is what you need but to check if Wi-Fi is `enabled` use:
    networksetup -getairportpower en0
    
    # Again, you will need to grep for the word: "off"
    

    For a more robust alternative, I would suggest you take a look at a simple bash utility I wrote called check written specifically for checking the connectivity of proxy servers. Spoiler: there is no magic here though; under-the-hood I am just leveraging bash native TCP/UDP sockets, albeit wrapped with a convenient set of options and insightful usage documentation.

    Finally, one slightly esoteric alternative that I have employed in macOS launchd daemons to pause execution (i.e. endlessly loop) until an internet connection is available:

    CheckForNetwork is shell function located in /etc/rc.common to check inet addresses. It is a useful utility but will not ensure internet connectivity (only ip address assignment) as opposed to the aforementioned alternatives which will verify connectivity.

    . /etc/rc.common
    
    CheckForNetwork
    while [ "${NETWORKUP}" != "-YES-" ]; do
      sleep 60
      NETWORKUP=
      CheckForNetwork
    done