Skip to content

Instantly share code, notes, and snippets.

@albertbori
Last active September 21, 2023 21:32
Star You must be signed in to star a gist
Embed
What would you like to do?
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
@andredewaard
Copy link

When I try to install this script on macOS 12.3.1 I get the following error. Can someone tell me how to resolve this the right way?

$ sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist

Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead.
`launchctl bootstrap` is a recommended alternative.
/Library/LaunchAgents/com.mine.toggleairport.plist: Path had bad ownership/permissions
Load failed: 122: Path had bad ownership/permissions

Changing the folder did not resolve the issue. launchctl bootstrap load /Library/LaunchAgents/com.mine.toggleairport.plist did also not work...

Reading the error message i think you still need to do:

chmod 600 /Library/LaunchAgents/com.mine.toggleairport.plist

@udayms
Copy link

udayms commented May 31, 2022

I am stuck with this problem as well.

sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead. 'launchctl bootstrap' is a recommended alternative. /Library/LaunchAgents/com.mine.toggleairport.plist: Path had bad ownership/permissions Load failed: 122: Path had bad ownership/permissions

Tried the CHMOD 600 suggestion above. But, still the problem persists.

@davelevine
Copy link

davelevine commented Jun 3, 2022

I found a different solution that I can confirm is working on macOS 12.4 Monterey. The script will enable or disable Wi-Fi depending on the status of the Ethernet port.

A few things to note…

  • Modify the ETHERNET_DEVICE with your respective device found in ifconfig. Mine happens to be en7, which is the Belkin USB-C LAN connection to my 2021 MBP.
  • Save the script to the ~/.local/bin folder and make it executable.
  • The script will not run automatically by default. I have it running every minute with crontab (crontab -e), but it can be adjusted accordingly depending on your needs. I'll include my crontab job below.
#!/bin/bash

ETHERNET_DEVICE=en7

NETWORKSETUP=/usr/sbin/networksetup
IFCONFIG=/sbin/ifconfig

WiFi=$($NETWORKSETUP -listallhardwareports | grep -A1 "Wi-Fi" | grep Device | cut -f2 -d' ')

echo "Run $0"
echo "Wifi interface $WiFi"
echo "Ethernet interface $ETHERNET_DEVICE"

EthernetStatus=$($IFCONFIG | grep -A5 $ETHERNET_DEVICE | grep status | cut -f2 -d' ')
echo "Ethernet is currently $EthernetStatus"

if [ "$EthernetStatus" != "active" ]; 
then 
	$NETWORKSETUP -setairportpower $WiFi on
	echo "Wi-Fi set on"
else
	$NETWORKSETUP -setairportpower $WiFi off
	echo "Wi-Fi set off"
fi

Crontab is below…

* * * * * ~/.local/bin/set_wifi_based_on_ethernet.sh >/dev/null 2>&1

@GuyZH
Copy link

GuyZH commented Jun 17, 2022

When I try to install this script on macOS 12.3.1 I get the following error. Can someone tell me how to resolve this the right way?

$ sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist

Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead.
`launchctl bootstrap` is a recommended alternative.
/Library/LaunchAgents/com.mine.toggleairport.plist: Path had bad ownership/permissions
Load failed: 122: Path had bad ownership/permissions

Changing the folder did not resolve the issue. launchctl bootstrap load /Library/LaunchAgents/com.mine.toggleairport.plist did also not work...

Reading the error message i think you still need to do:

chmod 600 /Library/LaunchAgents/com.mine.toggleairport.plist

I have the same problem, and the problem is not solved after entering CHMOD 600.
But after I typed launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist, I was notified by the script editor that it had been run.
But after I disconnected and reconnected the Ethernet, it didn't work...

@jgocobachi
Copy link

jgocobachi commented Sep 28, 2022

When I try to install this script on macOS 12.3.1 I get the following error. Can someone tell me how to resolve this the right way?

$ sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist

Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead.
`launchctl bootstrap` is a recommended alternative.
/Library/LaunchAgents/com.mine.toggleairport.plist: Path had bad ownership/permissions
Load failed: 122: Path had bad ownership/permissions

Changing the folder did not resolve the issue. launchctl bootstrap load /Library/LaunchAgents/com.mine.toggleairport.plist did also not work...

Reading the error message i think you still need to do:

chmod 600 /Library/LaunchAgents/com.mine.toggleairport.plist

I have the same problem, and the problem is not solved after entering CHMOD 600. But after I typed launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist, I was notified by the script editor that it had been run. But after I disconnected and reconnected the Ethernet, it didn't work...

After thoroughly reading through this https://gist.github.com/masklinn/a532dfe55bdeab3d60ab8e46ccc38a68 I have successfully ran this command to get this to work on any macOS 12.3.x or higher systems

sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15;

@bblater
Copy link

bblater commented Oct 7, 2022

When I try to install this script on macOS 12.3.1 I get the following error. Can someone tell me how to resolve this the right way?

$ sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist

Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead.
`launchctl bootstrap` is a recommended alternative.
/Library/LaunchAgents/com.mine.toggleairport.plist: Path had bad ownership/permissions
Load failed: 122: Path had bad ownership/permissions

Changing the folder did not resolve the issue. launchctl bootstrap load /Library/LaunchAgents/com.mine.toggleairport.plist did also not work...

Reading the error message i think you still need to do:

chmod 600 /Library/LaunchAgents/com.mine.toggleairport.plist

I have the same problem, and the problem is not solved after entering CHMOD 600. But after I typed launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist, I was notified by the script editor that it had been run. But after I disconnected and reconnected the Ethernet, it didn't work...

After thoroughly reading through this https://gist.github.com/masklinn/a532dfe55bdeab3d60ab8e46ccc38a68 I have successfully ran this command to get this to work on any macOS 12.3.x or higher systems

sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15;

I'm on 12.6 macOS and not getting the above change to launchctl to work. I run the following:
sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist
sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist
sudo ifconfig en0 down
sudo ifconfig en0 up

I don't see any errors, but if I do a launchctl list|grep -i 'com.mine' nothing shows. I am assuming that means it isn't running. Any suggestions on what I'm missing here?

After a reboot I tried the following again from above:
sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15;

Here is what I'm getting:
% sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15;
/Library/LaunchAgents/com.mine.toggleairport.plist: Could not find specified service
Boot-out failed: 113: Unknown error: 113
Could not find service.

When it says could not find specified service is the the toggleAirport.sh script listed in the .plist file or something else?

@arquer
Copy link

arquer commented Nov 16, 2022

Had to tweak the regular expression a bit (in my case I use an external Lenovo docking station) but after that it worked perfectly.
Maybe you could explain a little better how to debug though? for example, this is my first time using a script like that on Mac and I have no idea where the echos from that script are supposed to appear, so in my case not seeing them could either mean that the script was never running or I was looking in the wrong place...

@kMikaZu
Copy link

kMikaZu commented Jan 24, 2023

What if the Ethernet port belongs to a USB-adapter that is disconnected? Then the port disappears and it's impossible to check the status. How to solve this?

@kMikaZu
Copy link

kMikaZu commented Jan 24, 2023

How did you tweak it @arquer ?

@kMikaZu
Copy link

kMikaZu commented Jan 24, 2023

I found a different solution that I can confirm is working on macOS 12.4 Monterey. The script will enable or disable Wi-Fi depending on the status of the Ethernet port.

A few things to note…

  • Modify the ETHERNET_DEVICE with your respective device found in ifconfig. Mine happens to be en7, which is the Belkin USB-C LAN connection to my 2021 MBP.
  • Save the script to the ~/.local/bin folder and make it executable.
  • The script will not run automatically by default. I have it running every minute with crontab (crontab -e), but it can be adjusted accordingly depending on your needs. I'll include my crontab job below.
#!/bin/bash

ETHERNET_DEVICE=en7

NETWORKSETUP=/usr/sbin/networksetup
IFCONFIG=/sbin/ifconfig

WiFi=$($NETWORKSETUP -listallhardwareports | grep -A1 "Wi-Fi" | grep Device | cut -f2 -d' ')

echo "Run $0"
echo "Wifi interface $WiFi"
echo "Ethernet interface $ETHERNET_DEVICE"

EthernetStatus=$($IFCONFIG | grep -A5 $ETHERNET_DEVICE | grep status | cut -f2 -d' ')
echo "Ethernet is currently $EthernetStatus"

if [ "$EthernetStatus" != "active" ]; 
then 
	$NETWORKSETUP -setairportpower $WiFi on
	echo "Wi-Fi set on"
else
	$NETWORKSETUP -setairportpower $WiFi off
	echo "Wi-Fi set off"
fi

Crontab is below…

* * * * * ~/.local/bin/set_wifi_based_on_ethernet.sh >/dev/null 2>&1

Doesn't seem to work when the USB adapter is being removed @davelevine

@kMikaZu
Copy link

kMikaZu commented Jan 25, 2023

Found it, changed: sed -En 's/^\(Hardware Port: (.*Ethernet|USB 10.*), Device: (en.)\)$/\2/p'

@lxy1992
Copy link

lxy1992 commented Feb 20, 2023

Base on this script, I fix those problems and build a command tool to setup this function in one command. It works on Macbook Pro 14. Welcome to use it: https://github.com/lxy1992/mac-network-switch

@nilsou
Copy link

nilsou commented Feb 21, 2023

When I try to install this script on macOS 12.3.1 I get the following error. Can someone tell me how to resolve this the right way?

$ sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist

Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead.
`launchctl bootstrap` is a recommended alternative.
/Library/LaunchAgents/com.mine.toggleairport.plist: Path had bad ownership/permissions
Load failed: 122: Path had bad ownership/permissions

Changing the folder did not resolve the issue. launchctl bootstrap load /Library/LaunchAgents/com.mine.toggleairport.plist did also not work...

Reading the error message i think you still need to do:

chmod 600 /Library/LaunchAgents/com.mine.toggleairport.plist

I have the same problem, and the problem is not solved after entering CHMOD 600. But after I typed launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist, I was notified by the script editor that it had been run. But after I disconnected and reconnected the Ethernet, it didn't work...

After thoroughly reading through this https://gist.github.com/masklinn/a532dfe55bdeab3d60ab8e46ccc38a68 I have successfully ran this command to get this to work on any macOS 12.3.x or higher systems
sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15;

I'm on 12.6 macOS and not getting the above change to launchctl to work. I run the following: sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist sudo ifconfig en0 down sudo ifconfig en0 up

I don't see any errors, but if I do a launchctl list|grep -i 'com.mine' nothing shows. I am assuming that means it isn't running. Any suggestions on what I'm missing here?

After a reboot I tried the following again from above: sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15;

Here is what I'm getting: % sudo launchctl bootout system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo launchctl bootstrap system /Library/LaunchAgents/com.mine.toggleairport.plist; sudo ifconfig en0 down; sudo ifconfig en0 up; sudo sleep 15; /Library/LaunchAgents/com.mine.toggleairport.plist: Could not find specified service Boot-out failed: 113: Unknown error: 113 Could not find service.

When it says could not find specified service is the the toggleAirport.sh script listed in the .plist file or something else?

I was able to fix this issue by making the .plist owned by root and wheel:
sudo chown root:wheel /Library/LaunchAgents/com.mine.toggleairport.plist

and then running sudo launchctl load /Library/LaunchAgents/com.mine.toggleairport.plist again.

@bouzou4
Copy link

bouzou4 commented Jun 27, 2023

@albertbori I've fake-forked this into a repo with some small modifications for Ventura support and a simple automation script for install. Thanks for this awesome script!

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