5

I'm running Catalina, and the OS will always turn wifi on at boot. I've been looking into methods to turn wifi power off when I login, and I've created a .plist:

<?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.username.wifi_off</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/username/.wifi_off.sh</string>
  </array>
  <key>Nice</key>
  <integer>1</integer>
  <key>RunAtLoad</key>
  <true/>
  <key>StandardErrorPath</key>
  <string>/tmp/wifi_off.err</string>
  <key>StandardOutPath</key>
  <string>/tmp/wifi_off.out</string>
</dict>
</plist>

which is placed in ~/Library/LaunchAgents, and the file .wifi_off.sh is:

#!/bin/sh
networksetup -setairportpower en0 off

Is this quickest and/or most efficient way to disable wifi at login? How can this be extended to disable wifi at boot, so that wifi is disconnected at the login screen, before anyone has logged in?

  • I'm assuming that you want it off at boot/login but you still want to remember the networks to connect to at a later point, correct? If that's the case, don't run this as a launch agent, but as a launch daemon. https://apple.stackexchange.com/questions/249446/launchd-plist-format-for-running-a-command-at-a-specific-time-on-a-weekday/249452#249452 – Allan Jan 31 '20 at 06:26
  • 1
    Also, try using a logout hook to turn off WiFi when the user shuts down. WiFi power is persistent across reboots (my WiFi on my iMac is defaulted to off and stays that way across restarts) – Allan Jan 31 '20 at 06:29
  • Yeah, I was thinking the logout hook would be a great idea as well. But for the former, I can just move my .plist to /LaunchDaemons, and sudo launchctl load it, right? Do I need to launchctl unload the previous one at all? – irishwristwatch Jan 31 '20 at 07:07
  • 1
    if you put it in /Library/LaunchDaemons/ and make sure that it is owned by root, then you do not need sudo at all. And you don't need a separate shell script. You can just put /usr/sbin/networksetup -setairportpower en0 off in your plist as the ProgramArguments – TJ Luoma Feb 01 '20 at 03:04
  • 1
    If you're making changes to the plist, then yes, you should unload it. – Allan Feb 01 '20 at 04:54
  • I also ran across this...you might have to write a C++ app to make it work: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html#//apple_ref/doc/uid/TP30000905-CH219-CHDCEBBJ – Allan Feb 01 '20 at 05:04
  • I found one more in my travels today. This app allows you run scripts at certain events: https://apps.apple.com/us/app/eventscripts/id525319418?mt=12 I haven't tried it, but they offer a demo version This might be what you're looking for and at $4USD, it's a pretty good price, too. – Allan Feb 08 '20 at 01:18
  • @Allan. Interesting. So it seems there are more than a few ways to trigger events/scripts/whathaveyou. But I suppose that now begs the question: which of these occurs first? It might be interesting to test all of them in tandem, and somehow outputting the exact time each is executed to a logfile. I can see how this would be easy to integrate into the logouthook script, but could the crontab itself also output the time it is executed to a logfile? Potentially related: how would any of this show up when booting in verbose mode? – irishwristwatch Feb 08 '20 at 07:21
  • @TJ Luoma. I'm just now realizing exactly how your solution works. Mine was unnecessarily overcomplicated by one step, the separate shell script. I've read in places that crontab has been "deprecated" since 10.4, and that launchd should be used for these types of situations. Do you have any thoughts on one versus the other? – irishwristwatch Feb 08 '20 at 07:29
  • 1
    I know some folks like the simplicity of crontab, but launchd is the way to go. You're right that you don't need a separate script for this. If you find it doesn't work, it might need to be in LaunchDaemons instead (that runs as root). – TJ Luoma Feb 09 '20 at 01:02
  • @TJ Luoma. I've added code date >> /Users/username/Desktop/launchd_datestamp.txt to the crontab and logouthook, and they work reliably, however I cannot get the LaunchDaemon to write a file anywhere on the drive. Perhaps it is properly writing the file but it is not persistent? I have tried /tmp /Users/username/... and elsewhere. Any suggestions? – irishwristwatch Feb 10 '20 at 01:42
  • LaunchDaemons have to be stored in /Library/LaunchDaemons/ and have to be owned by root:wheel (sudo chown root:wheel /Library/LaunchDaemons/com.your.launchdfile.here.plist) If that's already set I'm not sure why it isn't working try adding StandardErrorPath and StandardOutPath to the plist – TJ Luoma Feb 10 '20 at 02:53
  • My attention was drawn to this Q&A because someone upvoted my answer earlier today. I see you have your own answer now, and that is fine. I also note that you've changed your question quite a lot. You went through several iterations of your ultimate goal, and then decided to remove the ultimate goal from your question entirely. Do you think that's helpful? I'm not saying it's un-helpful - I'm just curious. From where I sit, it does look like a moving target though. – Seamus Jun 05 '20 at 21:43
  • @Seamus: I suppose the "ultimate goal" changed once I realize what I was truly trying to do, namely prevent any wifi connection, whether to a known network or not. – irishwristwatch Jun 05 '20 at 23:39
  • Fair enough - Apple does mysterious things in mysterious ways. But some may wonder if that calls another question. You're not under a quota. – Seamus Jun 06 '20 at 00:08

2 Answers2

6

You may be asking two different things, but in the last paragraph you said:

The ultimate goal is to prevent the system from automatically logging into a network

Prevent System From Automatically Logging Into a Network:

I think the way to accomplish that is to un-check (disable) the Auto-Join feature for each WiFi network name/SSID that's stored. System Preferences, Network, Advanced.... Uncheck all checked boxes in the "Preferred Networks" list. enter image description here

Also note that there are a couple of other options here that may be of interest:

  • You can uncheck the option to "Remember networks this computer has joined"
  • You can check the box to "Require administrator authorization to: Turn Wi-Fi on or off.

To Disconnect WiFi Power at Boot Time:

To disconnect wifi power at boot time, you can use cron. It's certainly simpler than building a .plist, and it's invoked at boot instead of login. In my testing, it survives a login, but of course it could be "overruled" by other system settings -- YMMV. It can be re-started from the WiFi icon in the menu bar after login when you wish. Here's how to do this from the CLI:

crontab -e 

This will start your designated crontab editor, and open your current crontab. If you don't have a crontab (haven't used it previously), you'll be prompted to select from one of three choices for default editor. I'd suggest you choose pico or nano. That done, the default crontab will be opened in the editor of your choice.

Once the editor has started, make the following entry on the first empty line at the "bottom" the file:

@reboot /usr/sbin/networksetup -setairportpower en0 off

Save and exit the editor, and your new crontab becomes active. This command will now execute aach time your system boots, and (subject to the exception mentioned) your WiFi interface will be "OFF" until you turn it on.

Seamus
  • 4,547
  • So this is very helpful; I forgot about this option and I will use this. However, you're right that my original question asks two different things. For clarification, I'm looking to disconnect wifi power as well at boot or login. – irishwristwatch Jan 31 '20 at 05:45
  • 1
    @irishwristwatch: You've asked a very interesting question. I think my approach would be to disable the near-constant "network scanning" the system does instead of turning power off. (here's why) But I've not yet figured out how to do that. – Seamus Jan 31 '20 at 23:18
  • 1
    @irishwristwatch: Wrt your .plist, I'll mention this: 1.) A launchd 'User Agent' won't disable en0 until you log in. 2.) Consider the Launch Control app to use launchd; it will also allow you to invoke a System Agent 3.) If you wish to invoke at boot time, consider cron w/ @reboot schedule spec. (see revised answer) – Seamus Feb 01 '20 at 02:41
  • This "network scanning" to which you refer is very intriguing, but a little beyond me at the moment. Unless I'm missing something, that link states that this is problem in Linux and not in macOS. – irishwristwatch Feb 04 '20 at 23:46
  • @irishwristwatch: Yes - I was confused about the network scanning business - please ignore that comment. See my question here – Seamus Feb 05 '20 at 01:11
0

So I'm now using a combination of the crontab and the logouthook:

The crontab:

@reboot /usr/sbin/networksetup -setairportpower en0 off

The logout hook was generated like this:

#!/bin/sh
sudo defaults write com.apple.loginwindow LogoutHook ~/.logouthook
echo '#!/bin/sh\nnetworksetup -setairportpower en0 off' > ~/.logouthook
chmod +x ~/.logouthook

I have not found a way to always display wifi status at the login screen, but it seems to show wifi connectivity if it is connected to a network, and not show any status at all if it is not.

I think these two items (crontab and logouthook) in combination may be a complete solution here, but I will also test global /Library/LaunchAgents so that I would not have to repeat any procedures if I want this new feature to automatically be applied to any new user that is created.