Mac admin'ing

Running daily, weekly, and monthly scripts in macOS using periodic


I was looking for time-based project similar to Outset (which runs boot and login scripts stored in various directories), and apparently there’s one already baked into macOS that will run daily, weekly, and monthly scripts.

Shoutout to @elios on the MacAdmins Slack for letting me know about periodic

Launch Daemons

If you run sudo launchctl list | grep periodic-, you’ll see that these launch daemons are running:

And, though I don’t love SIP in general, it’s great for this, because you can’t actually disable the launch daemons:

sudo launchctl unload /System/Library/LaunchDaemons/
/System/Library/LaunchDaemons/ Operation not permitted while System Integrity Protection is engaged

So that means as long as you can enforce your daily, weekly, and monthly scripts being in the right place, with the right permissions, and with the right hash, they’ll be run regularly-ish.

Locations of Scripts

You can find scripts in /etc/periodic/daily, /etc/periodic/weekly, and /etc/periodic/monthly. You can also put your own scripts in there (root-owned, 755 permissions), and they’ll run alongside the ones that come with macOS.

According to /etc/defaults/periodic.conf, though, there’s another recommended place to put scripts:

# periodic script dirs

So that would be /usr/local/etc/periodic/daily, /usr/local/etc/periodic/weekly, and /usr/local/etc/periodic/monthly. Having your scripts separated from the built-in scripts may be a good idea, even though they’ll run fine alongside the built-in scripts.


If your script has any echo commands, the output will go to the appropriate log file (by default, those logs would be /var/log/daily.out, /var/log/weekly.out, and /var/log/monthly.out), but there won’t necessarily (again, with the default settings) be any other indicators in the daily, weekly, and monthly logs that your scripts ran.

The format of the log seems to be a date/time, all the echo statements from the scripts run, and then a closer like -- End of daily/weekly/monthly output --.

Invoking manually

If you don’t want to wait until the next day, week, or month, you can do some manual testing by running a command like this, for example: sudo periodic daily

No TCC/PPPC support

Allowing full disk access to a script relies on giving that access to the actual parent process. As far as I can tell, the parent process is the /usr/sbin/periodic binary, but that binary (although shipped with macOS) isn’t code-signed.

Mac admin'ing

Python script to list software available in a Munki repo

I created a small project (for fun) to list out software available in a Munki repo. It’s called MunkiItemsList.

On a basic level, it looks for all the items that are listed in any optional installs manifest, and then lists out the display name, description, and highest version available. There are some additional options described in detail in the README.

Mac admin'ing

Python 3 script to add optional installs to the SelfServeManifest

Two years ago, I wrote a bash script that adds a bunch of optional installs to the SelfServeManifest using /usr/libexec/PlistBuddy, which is a fine tool, but it can get bit messy sometimes. I did play around with using /usr/local/munki/manifestutil, but it got a bit convoluted, and I figured “Hey, why not just write it in Python 3, now that the default shell is zsh instead of bash and Python 2 is end-of-life?”

So, yeah, the rationale here is that you may want to have a bunch of applications installed as default applications for your users but still give users the option to remove those applications later, so this Python 3 script would just make it seem to Munki as if the user has already selected these optional installs to install… and then she can always use Managed Software Center to remove those optional installs later if she doesn’t want them any more.