Posted on 11-05-2015 01:14 PM
We are more than half way through our upgrade process. Clients are on 10.10.5 and hardware are a variety of Retina MacBook Pros and MacBook Airs. Image was created in AutoDMG. Usually the users may go back to their desk and plug into Ethernet using Apple Thunderbolt or USB adapters after they've come back from a meeting. However, it seems that the wireless still seems to have priority even though Ethernet is detected. You have to actively turn off and on wireless for Ethernet to take priority again. This becomes very obvious when uploading or downloading files from/to a server share.
Apple by default sets Thunderbolt and USB adapters to be above Wireless and that's the case across all these machines. Has anyone seen this behavior?
Posted on 11-05-2015 01:19 PM
We have a wireless "switcher" process, run by a LaunchDaemon that detects when Ethernet is plugged in and turns off wireless. We do this to prevent network bridging for one thing, but also because, why hog a wireless connection if your Mac has a valid Ethernet connection? You might want to consider using something like that to help. As far as I know, this behavior isn't really new to 10.10.5. We've had similar issues of the network connection going through wireless even when Enet is active for years now (hence why we have the switcher process)
Posted on 11-05-2015 01:41 PM
Can you share more a bit more on that switcher? Scripts, etc.
Also, this didn't seem to be an issue in 10.8 or 10.9 for our users.
Posted on 11-05-2015 01:59 PM
Sanitized version of the LaunchDaemon (names changed, but the basics are all there)
<?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.company.wiredswitcher</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Scripts/company/airport_off.sh</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration</string>
</array>
<key>UserName</key>
<string>root</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
I will see if I can post the script later. It was put together by someone else before I came onboard so I just need to get an OK to post it, or post an alternate version if need be, but high level, it figures out which "port" is wireless (Wi-Fi or AirPort depending on the OS), then looks at all "Ethernet" connections and sees if any of them are set to "active" by doing something like
ifconfig en1 | awk -F': ' '/status/{print $NF}'
If any "Ethernet" designated port is showing as "active" from the above command, it will run a:
networksetup -setairportpower $wifi off
on whichever port is the wireless one.
Posted on 11-06-2015 11:01 AM
Hey @bpavlov Just as a quick follow up, here's a script that can be used in conjunction with the above LaunchDaemon (you could potentially also use a cached offline policy that uses the Network State change trigger, but may not be as reliable as a local daemon)
I reworked this script almost from scratch since I didn't feel comfortable posting the original version, so this is a bit different than what we use, but has the same principle.
#!/bin/bash
WIFIPORT=$(networksetup -listallhardwareports | awk '/Wi-Fi|AirPort/{getline; print $NF}')
ETHERPORTS=$(networksetup -listallhardwareports | grep -A1 "Hardware Port:.*Ethernet" | awk -F': ' '/Device:/{print $NF}')
ETHERNAMES=$(networksetup -listallhardwareports | awk -F': ' '/Hardware Port:.*Ethernet/{print $NF}')
for i in $ETHERPORTS; do
ENETPORTS+=("$i")
done
for a in "$ETHERNAMES"; do
ENETNAMES+=("$a")
done
x=0
while read PORT; do
if [[ $(ifconfig ${ENETPORTS[$x]} | awk '/status:/{print $NF}') == "active" ]]; then
echo "${ENETNAMES[$x]} was active. Setting Wi-Fi to Off."
networksetup -setairportpower $WIFIPORT off
WIFIOFF="yes"
break
else
echo "${ENETNAMES[$x]} was not active. Continuing..."
fi
let x=$((x+1))
done < <(printf '%s
' "${ENETPORTS[@]}")
if [ "$WIFIOFF" ]; then
echo "Wi-Fi was disabled"
else
echo "Wi-Fi was not disabled"
fi
sleep 10
Essentially, figure out which port is Wi-Fi or AirPort, build a list of all hardware Ethernet ports, then place them into an array and loop over each "Ethernet" port and check to see if its status is "active" If so, run a command to turn off Wi-Fi and break from the loop. If none are active, just exit.
The 10 second sleep at the end is to prevent launchd from "throttling" the job run if it tries again too soon, and spewing a bunch of errors into the system.log about it.
Posted on 11-09-2015 02:51 AM
We have a similar thing. Turns off Wi-Fi if there is an active Ethernet and informs user as such. If the script turned off Wi-Fi, then on a disconnect it turns Wi-Fi back on, else Wi-Fi stays off on a disconnect. The script only bothers if it is on our domain. It also renews dhcp to ensure our DHCP/DNS servers have the correct record.
Same reasons, don't want people bridging networks and wasting Wi-Fi addresses. Same trigger method.
Posted on 02-14-2016 01:09 AM
Hey @mm2270 I want to pick your brain on something in this script. Anyone is really welcome to answer this as I'm just trying to get a better understanding here. For the most part, I'm following the logic and flow of the script. With any script, I like to see what bash is actually doing when it executes so I ran it as bash -x /path/to/script.sh in the command line.
I've been testing it out and comparing the values of the variables and arrays. On my MacBook Retina, for example, I have just 1 TB Ethernet adapter which should mean the array "${ENETPORTS[@]}" should only have 1 entry which is en3 in my case. The for loop computes this correctly. In testing I could echo the values of variables and arrays before the while loop starts. Everything is adding up so far.
However it looks like for whatever reason the ENETPORTS array when fed into the while loop is counting ALL the network interfaces on my computer which is 9 when it should really just be counting 1 interface. I believe it has something to do specifically with this:
$(printf '%s
' "${ENETPORTS[@]}").
Am I going crazy? Shouldn't the while loop stop after it goes through all the ports that have Ethernet in it which should mean that it would stop after 1 run? As you will see the first run of the while loop does what it's supposed to. After that, it does not do what I expect it to do. Along the same lines if the logic I'm following holds true, is the "break" command actually necessary there as well?
For the record, I copied and pasted the script as was and it didn't execute so I had to fix the error on line 26 of your script. So I'm copying the script as I ran it with the minor changes I made:
#!/bin/bash -x
WIFIPORT=$(networksetup -listallhardwareports | awk '/Wi-Fi|AirPort/{getline; print $NF}')
ETHERPORTS=$(networksetup -listallhardwareports | grep -A1 "Hardware Port:.*Ethernet" | awk -F': ' '/Device:/{print $NF}')
ETHERNAMES=$(networksetup -listallhardwareports | awk -F': ' '/Hardware Port:.*Ethernet/{print $NF}')
for i in $ETHERPORTS; do
ENETPORTS+=("$i")
done
for a in "$ETHERNAMES"; do
ENETNAMES+=("$a")
done
x=0
while read PORT; do
if [[ $(ifconfig ${ENETPORTS[$x]} | awk '/status:/{print $NF}') == "active" ]]; then
echo "${ENETNAMES[$x]} is active. Setting Wi-Fi to Off."
networksetup -setairportpower $WIFIPORT off
break
else
echo "${ENETNAMES[$x]} is not active. Continuing..."
fi
let x=$((x+1))
done <<$(printf '%s
' "${ENETPORTS[@]}")
if [ $(networksetup -getairportpower "$WIFIPORT" | awk '{print $NF}') = "Off ]; then
echo "Wi-Fi was disabled."
else
echo "Wi-Fi was not disabled."
exit 1
fi
sleep 10
Here's the executable output:
++ networksetup -listallhardwareports
++ awk '/Wi-Fi|AirPort/{getline; print $NF}'
+ WIFIPORT=en0
++ networksetup -listallhardwareports
++ grep -A1 'Hardware Port:.*Ethernet'
++ awk '-F: ' '/Device:/{print $NF}'
+ ETHERPORTS=en3
++ networksetup -listallhardwareports
++ awk '-F: ' '/Hardware Port:.*Ethernet/{print $NF}'
+ ETHERNAMES='Thunderbolt Ethernet'
+ for i in '$ETHERPORTS'
+ ENETPORTS+=("$i")
+ for a in '"$ETHERNAMES"'
+ ENETNAMES+=("$a")
+ x=0
++ networksetup -getairportpower en0
++ awk '{print $NF}'
+ read PORT
++ ifconfig en3
++ awk '/status:/{print $NF}'
+ [[ inactive == ac ive ]]
+ echo 'Thunderbolt Ethernet is not active. Continuing...'
Thunderbolt Ethernet is not active. Continuing...
+ let x=1
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=2
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=3
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=4
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=5
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=6
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=7
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=8
+ read PORT
++ ifconfig
++ awk '/status:/{print $NF}'
+ [[ active
inactive
inactive
inactive
active
inactive
inactive == ac ive ]]
+ echo ' is not active. Continuing...'
is not active. Continuing...
+ let x=9
+ read PORT