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
@kMikaZu
Copy link

kMikaZu commented Jul 8, 2024

I had the same experiences.

@adamshand
Copy link

Not sure what's going on sorry. The error message indicates that macOS thinks you are running the command as root.

Can you show me the entire terminal session and exactly how you are installing it?

@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