Turn wifi on/off based on ethernet status?

Recently I acquired a docking station with an ethernet port. I’d like to setup my Mac to automatically disable WiFi when my laptop is connected to the dock (and thus to an ethernet connection).

I’m aware that I can set the network interface order so that traffic will preferentially travel over ethernet when it’s available, but I’d like to disable the WiFi.

Seems like there should be something that does this? I found this thread, but I don’t believe any of these options work under BigSur.

Many thanks for any suggestions,
Adam.

I believe if you want to use features like AirDrop and Apple Watch unlocking, you’d need to keep wifi active.

However, if you don’t want these features, you should be able to use Keyboard Maestro (KM) and Network Locations to achieve this. If you create a new network location in the Network preferences pain that only has Ethernet/Dock enabled, you can have KM switch between network locations when you plug the dock in to the Mac.

@drezha is absolutely right: Keyboard Maestro is the way to go — at least this worked well for me. :slight_smile:

Regarding Wi-Fi toggle based on Ethernet status
Two rules come into play: both with “This USB devices with name containing {{LAN}}” is attached/detached. If this happens, a shell script action runs.

networksetup -setairportpower en0 on

{{LAN}} may be different with your dock/Ethernet, but I’d give it a try. “en0 on” is respectively “en0 off” within the subsequent rule. More info regarding networksetup: GitHub - kendfinger/MacHack: Hidden Tools in macOS

Unlock with Apple Watch, despite attached Ethernet cable
This was a bit trickier for me and might differ with your use case / behavior. This also utilizes two rules, the first addressing the scenario that Ethernet is active.

Using the idle trigger after {{n Minutes}} networksetup does its work and activates Wi-Fi (same line as quoted above). Then a small pause gives KM some time and a variable named “SystemLockActive” is set to 1. Then I run a shell script which starts the screensaver:

/System/Library/CoreServices/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine

The second rule addresses the scenario that I log in, and the device uses Ethernet. As a trigger, I use my most performed behavior after login: Alfred activates. Granted: this might not happen immediately but that’s no problem for me. When it happens an if statement checks if the USB device {{LAN}} exists and if the Variable “SystemLockActive” is set to 1. If all this is true networksetup comes into play again:

networksetup -setairportpower en0 off

Finally: The variable SystemLockActive needs to be set to 0 so the next time the dance works out again.

For me, this works fine since Big Sur and also on Monterey. It has not caused any troubles or hiccups. I just didn’t want to miss the experience of unlocking with Apple Watch. Good luck with your endeavor.

1 Like

Just a tip that en0 is usually the port used for built-in Ethernet.

For a laptop, your AirPort (Wi-Fi) will be en0. For a Mac Mini (and I assume iMac/Mac Pro), it will be your wired Ethernet port, and Wi-Fi will be en1

If you aren’t sure, you can use:

networksetup -listallhardwareports

to show a list of all the ports that the Mac has.


I used to do this with a launchd trigger that looked for changes to a particular folder, but with AirDrop, I want to leave Wi-Fi on, and don’t see much point in turning off Wi-Fi when Ethernet is enabled anyway, so I haven’t checked to see if it still works. That said, if anyone is interested in seeing it, I can dig it out.

1 Like

This should do it, and assumes some comfort with Terminal commands and the like.
You can use this script to set Wi-Fi based on the status of the Ethernet port (here assumed to be en0).

#!/bin/bash

ETHERNET_DEVICE=en0

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" == "inactive" ]; 
then 
	$NETWORKSETUP -setairportpower $WiFi on
	echo "Wi-Fi set on"
else
	$NETWORKSETUP -setairportpower $WiFi off
	echo "Wi-Fi set off"
fi

Now the problem is doing this automatically.
You could use KeyboardMaestro to run the script periodically.
Or you could use crontab.
Your crontab job (use crontab -e to edit it) would look like this to have the script run every minute:

*/1 * * * * ~/.local/bin/set_wifi_based_on_ethernet.sh

(I saved my set_wifi_based_on_ethernet.sh script into my ~/.local/bin folder. Be sure to make it executable.)

2 Likes

Thank you all, that’s very helpful!

A cronjob running every minute would be good enough, but I’ve been looking for a reason to play with Keyboard Maestro and never found one … now I do! Fun! :slight_smile:

1 Like

I adjusted the script above. So it works with all interfaces, detects air plain mode etc.

#!/bin/bash
# Version 2.0 - by Joerg Miersch on June 10, 2024
# Script detects whether a network interface other then "Wi-Fi" is connected and disables "Wi-Fi" in case another
# active interface has been found.

# To use iPhone via USB-cable, it is necessary to disable "Wi-Fi" manually to discover the iPone as such other interface.   
# In case no visible SSID can be detected, the script assumes that the device is running in an WLAN free environment
# like aircrafts or sensitive areas of hospitals and disables the "Wi-Fi" interface.

#clear
#echo "Run $0"

#ETHERNET_DEVICE=en0

NETWORKSETUP=/usr/sbin/networksetup
IFCONFIG=/sbin/ifconfig
AIRPORT=/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport

# Get number of hardware interfaces
DevCount=$($NETWORKSETUP -listallhardwareports | grep Device -c)


#write first part of interface Type name of all interfaces (3rd parameter in output line 0) in variable interfaces
interfaces=$($NETWORKSETUP -listallhardwareports | grep -A0 "Hardware Port" | cut -f 3 -d' ');



#write device name of all interfaces in variable devices
devices=$($NETWORKSETUP -listallhardwareports | grep Device | cut -f 2 -d' ');



#write first part of interface Type name in interface[i] and interface name in device[i]
for ((i=0;i<$DevCount;i++)); 
  do 
	interface[$i]=$(echo $interfaces | cut -f $((i+1)) -d' ');
	device[$i]=$(echo $devices | cut -f $((i+1)) -d' ');
	#echo Interface ${interface[$i]} is related to Device ${device[$i]}
	
  done



#write status of interface name in status[i]
DEV=en500
for ((i=0;i<$DevCount;i++)); 
  do 
	DEV=$(echo ${device[$i]}:)
	status[$i]=$($IFCONFIG | grep -A10 "$DEV" | grep "status" | cut -f2 -d' ')
	#echo Interface ${interface[$i]} is related to Device ${device[$i]} with Status ${status[$i]}
	
  done



#Init Ethernetstatus
EthernetStatus="inactive"

#To prepare activation of  "Wi-Fi" in case there is no another active interface:
# - determinate WiFi interface 
# - check network status of all other interfaces is not "active"
i=0
while [ $i -lt $DevCount ]
  do		
	if [ ${interface[$i]} == "Wi-Fi" ] 
		then
			WiFi=${device[$i]}
 		
		else if [[ ${status[$i]} == "active" ]]
			then 
				EthernetStatus=${status[$i]};
		     fi
	fi
	i=$((i+1));		
  done

#echo "WIFI interface is $WiFi"
#echo "Netzwerk Status is" $EthernetStatus




if [ "$EthernetStatus" == "inactive" ] 
then 
	$NETWORKSETUP -setairportpower $WiFi on
	#echo "Wi-Fi set on";
	AirportStatus=$($AIRPORT -s);
	#echo $AirportStatus;
	if [ "$AirportStatus" == "No networks found" ]
	then
		$NETWORKSETUP -setairportpower $WiFi off;
		#echo "No active WLAN SSID fond => Wi-Fi set off";
	fi;
else
	$NETWORKSETUP -setairportpower $WiFi off
	#echo "Wi-Fi set off"
fi

3 Likes

If you’re after a less technical option, you can probably do this with Apple Shortcuts as well. I’ve not looked at the Mac version for a while but I would assume you could say something like “When device is plugged in, turn off wifi” and vice versa. (I assume your docking station charges as well.)

1 Like