Last active
September 26, 2021 21:16
-
-
Save amekusa/168ba3a60517ece3217a3111c8be3058 to your computer and use it in GitHub Desktop.
Mac WiFI Monitor; A bash script that keeps checking if the WiFi connection alive on your Mac by continuously sending pings to the router and public DNSes. If the connection seemed lost nonetheless, the script automatically restarts the WiFi adapter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Mac WiFi Monitor | |
| # ------------------ ---- -- - | |
| # Keeps checking if the WiFi connection alive | |
| # by continuously sending pings to the router and public DNSes. | |
| # If the connection seemed lost nonetheless, | |
| # automatically restarts the WiFi device on your Mac | |
| # ==================================================== | |
| # Author: amekusa.com | |
| # Version: 2.2.0 | |
| # Updated: 2021-09-27 | |
| # ---- Settings -------- | |
| # Network device to monitor (leave it commented out to automatically detect the WiFi device) | |
| # DEV=en1 | |
| # NOTE: To list all the devices: | |
| # $ networksetup -listallhardwareports | |
| PING_TO=(192.168.1.1 1.1.1.1 8.8.8.8 4.2.2.2) | |
| PING_INTERVAL=3 # seconds | |
| PING_TIMEOUT=1 # seconds | |
| PING_SIZE=0 # bytes | |
| AUDIBLE_ALERTS=true # true or false | |
| PROMPT_RESTART=false # true or false | |
| LOG_TO_FILE=true # true or false | |
| LOG_FILE="$HOME/.wifi-monitor.log" | |
| SYSLOG=false # true or false | |
| # NOTE: syslog on High Sierra is broken | |
| # ==== END Settings ==== | |
| trap _quit SIGINT | |
| _quit() { | |
| echo | |
| _ts; _log "Finished by user input @ $ts" | |
| exit | |
| } | |
| _ts() { | |
| ts=$(date +'%H:%M:%S %b %d, %Y') | |
| } | |
| _log() { | |
| [ "$log" = "$1" ] && return # don't repeat the same message | |
| $LOG_TO_FILE && echo "$1" >> $LOG_FILE | |
| $SYSLOG && syslog -s "[WiFi Monitor] $1" | |
| echo "$1" | |
| log="$1" | |
| } | |
| _active() { | |
| [[ $(networksetup -getairportpower $DEV) == *On ]] | |
| } | |
| _ping() { | |
| ping -c 1 -s $PING_SIZE -t $PING_TIMEOUT -n ${PING_TO[$1]} &> /dev/null | |
| } | |
| _restart() { | |
| _log "Restarting $DEV ..." | |
| networksetup -setairportpower $DEV off | |
| sleep 1 | |
| networksetup -setairportpower $DEV on | |
| _state 1 | |
| } | |
| _state() { | |
| _ts | |
| case $1 in | |
| 0) _log "The device got deactivated @ $ts" ;; | |
| 1) _log "The device got activated @ $ts" ;; | |
| 2) _log "Internet connection alive @ $ts" ;; | |
| esac | |
| state=$1 | |
| } | |
| _loop() { | |
| case $state in | |
| 2) # online | |
| i=0 | |
| _log "Started pinging to ${PING_TO[$i]} ..." | |
| while [ $i -le $iMax ]; do | |
| if _ping $i; then | |
| if [ $i -gt 0 ]; then | |
| _log " Ping to ${PING_TO[$i]} succeeded" | |
| i=0 | |
| fi | |
| sleep $PING_INTERVAL | |
| else # ping failed | |
| if ! _active; then | |
| _state 0; sleep 1 | |
| return | |
| fi | |
| if [ $i -eq 0 ]; then | |
| _ts | |
| elif $AUDIBLE_ALERTS && [ $i -lt $iMax ]; then | |
| afplay -v .5 /System/Library/Sounds/Hero.aiff & | |
| fi | |
| _log "!) Ping to ${PING_TO[$i]} failed" | |
| ((i++)) | |
| fi | |
| done | |
| _log "!) Connection lost @ $ts" | |
| $AUDIBLE_ALERTS && afplay /System/Library/Sounds/Purr.aiff & | |
| if $PROMPT_RESTART; then | |
| while true; do | |
| read -n 1 -p "Restart WiFi device (Y/N) ? " answer | |
| echo | |
| case $answer in | |
| [Yy]) _restart; return ;; | |
| [Nn]) _ts; _log "Resumed monitoring $DEV @ $ts"; return ;; | |
| *) echo "!) Type Y to restart, N to continue monitoring" ;; | |
| esac | |
| done | |
| fi | |
| _restart | |
| ;; | |
| 1) # device active | |
| i=0 | |
| while ! _ping $i; do | |
| _log "Waiting for internet connection ..." | |
| if ! _active; then | |
| _state 0; sleep 1 | |
| return | |
| fi | |
| if [ $i -ge $iMax ]; then i=0; else ((i++)); fi | |
| done | |
| $AUDIBLE_ALERTS && afplay -v .5 /System/Library/Sounds/Submarine.aiff & | |
| _state 2; sleep $PING_INTERVAL | |
| ;; | |
| 0) # device inactive | |
| while ! _active; do | |
| _log "Waiting for the device to be activated ..." | |
| sleep 1 | |
| done | |
| _state 1 | |
| ;; | |
| esac | |
| } | |
| # ---- Initialize -------- | |
| # clear the existing log file | |
| $LOG_TO_FILE && [ -f $LOG_FILE ] && true > $LOG_FILE | |
| # initialize variables | |
| [ -z $DEV ] && DEV=$(networksetup -listallhardwareports | awk -F': ' '/Wi-Fi/{getline; print $2;}') | |
| iMax=$((${#PING_TO[@]}-1)) # PING_TO.length - 1 | |
| if _active; then | |
| state=1 | |
| else | |
| state=0; sleep 1 | |
| fi | |
| # ---- Main -------- | |
| _log "Monitoring the network device '$DEV' ..." | |
| while _loop; do | |
| : # noop | |
| done | |
| _ts; _log "The script stopped due to an unknown error @ $ts" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This bash script continuously sends pings to public DNSes at 3-seconds intervals to keep internet connection alive.
If the connection was lost nonetheless for whatever reason, the script automatically restarts the WiFi device.