Skip to content

Instantly share code, notes, and snippets.

@albertbori
Last active November 13, 2024 14:21
Show Gist options
  • Save albertbori/1798d88a93175b9da00b to your computer and use it in GitHub Desktop.
Save albertbori/1798d88a93175b9da00b to your computer and use it in GitHub Desktop.
Automatically disable Wifi when an Ethernet connection (cable) is plugged in on a Mac
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.asb.toggleairport</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/Library/Scripts/toggleAirport.sh</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration</string>
</array>
</dict>
</plist>

Overview

This is a bash script that will automatically turn your wifi off if you connect your computer to an ethernet connection and turn wifi back on when you unplug your ethernet cable/adapter. If you decide to turn wifi on for whatever reason, it will remember that choice. This was improvised from this mac hint to work with Yosemite, and without hard-coding the adapter names. It's supposed to support growl, but I didn't check that part. I did, however, add OSX notification center support. Feel free to fork and fix any issues you encounter.

Most the credit for these changes go to Dave Holland.

Requirements

  • Mac OSX 10+
  • Administrator privileges

Installation Instructions

  • Copy toggleAirport.sh to /Library/Scripts/
  • Run chmod 755 /Library/Scripts/toggleAirport.sh
  • Copy com.mine.toggleairport.plist to /Library/LaunchAgents/
  • Run chmod 600 /Library/LaunchAgents/com.mine.toggleairport.plist
  • Run sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist to start the watcher

Uninstall Instructions

  • Run sudo launchctl unload /Library/LaunchAgents/com.mine.toggleairport.plist to stop the watcher
  • Delete /Library/Scripts/toggleAirport.sh
  • Delete /Library/LaunchAgents/com.mine.toggleairport.plist
  • Delete /private/var/tmp/prev_eth_on
  • Delete /private/var/tmp/prev_air_on

Misc

To debug, just run: sudo /Library/Scripts/toggleAirport.sh and add echo's wherever you'd like

#!/bin/bash
function set_airport {
new_status=$1
if [ $new_status = "On" ]; then
/usr/sbin/networksetup -setairportpower $air_name on
touch /var/tmp/prev_air_on
else
/usr/sbin/networksetup -setairportpower $air_name off
if [ -f "/var/tmp/prev_air_on" ]; then
rm /var/tmp/prev_air_on
fi
fi
}
function growl {
# Checks whether Growl is installed
if [ -f "/usr/local/bin/growlnotify" ]; then
/usr/local/bin/growlnotify -m "$1" -a "AirPort Utility.app"
else
osascript -e "display notification \"$1\" with title \"Wifi Toggle\" sound name \"Hero\""
fi
}
# Set default values
prev_eth_status="Off"
prev_air_status="Off"
eth_status="Off"
# Grab the names of the adapters. We assume here that any ethernet connection name ends in "Ethernet"
eth_names=`networksetup -listnetworkserviceorder | sed -En 's|^\(Hardware Port: .*Ethernet, Device: (en.)\)$|\1|p'`
air_name=`networksetup -listnetworkserviceorder | sed -En 's/^\(Hardware Port: (Wi-Fi|AirPort), Device: (en.)\)$/\2/p'`
# Determine previous ethernet status
# If file prev_eth_on exists, ethernet was active last time we checked
if [ -f "/var/tmp/prev_eth_on" ]; then
prev_eth_status="On"
fi
# Determine same for AirPort status
# File is prev_air_on
if [ -f "/var/tmp/prev_air_on" ]; then
prev_air_status="On"
fi
# Check actual current ethernet status
for eth_name in ${eth_names}; do
if ([ "$eth_name" != "" ] && [ "`ifconfig $eth_name | grep "status: active"`" != "" ]); then
eth_status="On"
fi
done
# And actual current AirPort status
air_status=`/usr/sbin/networksetup -getairportpower $air_name | awk '{ print $4 }'`
# If any change has occured. Run external script (if it exists)
if [ "$prev_air_status" != "$air_status" ] || [ "$prev_eth_status" != "$eth_status" ]; then
if [ -f "./statusChanged.sh" ]; then
"./statusChanged.sh" "$eth_status" "$air_status" &
fi
fi
# Determine whether ethernet status changed
if [ "$prev_eth_status" != "$eth_status" ]; then
if [ "$eth_status" = "On" ]; then
set_airport "Off"
growl "Wired network detected. Turning AirPort off."
else
set_airport "On"
growl "No wired network detected. Turning AirPort on."
fi
# If ethernet did not change
else
# Check whether AirPort status changed
# If so it was done manually by user
if [ "$prev_air_status" != "$air_status" ]; then
set_airport $air_status
if [ "$air_status" = "On" ]; then
growl "AirPort manually turned on."
else
growl "AirPort manually turned off."
fi
fi
fi
# Update ethernet status
if [ "$eth_status" == "On" ]; then
touch /var/tmp/prev_eth_on
else
if [ -f "/var/tmp/prev_eth_on" ]; then
rm /var/tmp/prev_eth_on
fi
fi
exit 0
@JtwoA
Copy link

JtwoA commented Sep 30, 2024

I got an error when following these instructions. macOS Sonoma, M1 MacBook Air.

Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead. launchctl bootstrap is a recommended alternative. Load failed: 5: Input/output error Try running launchctl bootstrap as root for richer errors.

I just got a similar thing on Sequoia, @adamshand

/wifi-toggle.sh: line 53: /Users/john/Library/LaunchAgents/nz.haume.wifi-toggle.plist: Permission denied
Enabling launchd service: nz.haume.wifi-toggle
Bootstrap failed: 5: Input/output error
Try re-running the command as root for richer errors.
john@Johns-M1 Downloads % chmod +x wifi-toggle.sh 
john@Johns-M1 Downloads % ./wifi-toggle.sh on    
DEBUG: is_launchd_loaded(): nz.haume.wifi-toggle not loaded
Creating launchd service: /Users/john/Library/LaunchAgents/nz.haume.wifi-toggle.plist
./wifi-toggle.sh: line 53: /Users/john/Library/LaunchAgents/nz.haume.wifi-toggle.plist: Permission denied
Enabling launchd service: nz.haume.wifi-toggle
Bootstrap failed: 5: Input/output error
Try re-running the command as root for richer errors.

@adamshand
Copy link

It's not working because you don't have permission to write to the LaunchAgents directory;

/wifi-toggle.sh: line 53: /Users/john/Library/LaunchAgents/nz.haume.wifi-toggle.plist: Permission denied

@JtwoA
Copy link

JtwoA commented Oct 4, 2024

It's not working because you don't have permission to write to the LaunchAgents directory;

/wifi-toggle.sh: line 53: /Users/john/Library/LaunchAgents/nz.haume.wifi-toggle.plist: Permission denied

Yep - that did it. Now to see if this handled the move to Sequoia. Will let you know.

Thanks!

@andy16666
Copy link

Works. For my case, I had to tweak the regex as follows to account for differences in naming:

eth_names=`networksetup -listnetworkserviceorder | sed -En 's|^\(Hardware Port: .*Ethernet.*, Device: (en.+)\)$|\1|p'`

. This is my network list:

% networksetup -listnetworkserviceorder
An asterisk (*) denotes that a network service is disabled.
(1) Thunderbolt Ethernet Slot 0
(Hardware Port: Thunderbolt Ethernet Slot 1, Device: en10)

(2) Thunderbolt Ethernet Slot 1
(Hardware Port: Thunderbolt Ethernet Slot 1, Device: en12)

(3) USB 10/100/1G/2.5G LAN
(Hardware Port: USB 10/100/1G/2.5G LAN, Device: en8)

(4) Thunderbolt Bridge
(Hardware Port: Thunderbolt Bridge, Device: bridge0)

(5) Targus USB3 DV4K DOCK w PD60W
(Hardware Port: Targus USB3 DV4K DOCK w PD60W, Device: en7)

(6) USB 10/100/1000 LAN
(Hardware Port: USB 10/100/1000 LAN, Device: en6)

(7) Wi-Fi
(Hardware Port: Wi-Fi, Device: en0)

.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment