Skip to content

Instantly share code, notes, and snippets.

@clarityD
Last active April 3, 2023 08:03
Show Gist options
  • Save clarityD/3aa0a182a47a1e3d3033365539c74b6b to your computer and use it in GitHub Desktop.
Save clarityD/3aa0a182a47a1e3d3033365539c74b6b to your computer and use it in GitHub Desktop.
Run scheduled jobs by user with launchd in macOS

Automating Homebrew Updates with Launchd

I have been using homebrew since 2016, but I frequently forgot to update brew and upgrade the installed packages. As I have been programming more, I wanted to find a way to automate the homebrew update/upgrade process.

Seeking Help from ChatGPT

I initially considered creating a shell script, but since I don't know shell scripting, I asked ChatGPT how to do it. I knew bash better than what I was currently using, zshell, and I was unaware of the differences in syntax or commands between the two. As I was querying the AI, I asked it if there was a way to run a program automatically. It reminded me of cron. At this point, I recalled that macOS also has another scheduling system, launchd.

https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html

The Solution

I went on to ask ChatGPT, and the AI provided instructions for using launchd:

launchctl load /Library/LaunchDaemons/com.company.brew.update.plist

I knew homebrew changed its configuration to discourage users from running as the root user in March 2021, and I suspected running the scheduler as ChatGPT suggested would be as the root user. Ding! Ding! I was right!

ChatGPT also generated the XML plist file with the keys and values, but it took the AI a few tries to get it right.

Launchd Configuration

To create a user-executed scheduled task, place the com.yourcompany.brew.update.plist file in (replacing the yourcompany with either your computer name or something that makes sense to you):

~/Library/LaunchAgents/

And run the following command:

Guest on Zeus command 929 : launchctl bootstrap gui/$(id -u) /Users/Guest/Library/LaunchAgents/com.yourcompany.brew.update.plist

If you need to stop the scheduled job (or make changes), run the following:

Guest on Zeus command 930 : launchctl bootout gui/$(id -u) /Users/Guest/Library/LaunchAgents/com.yourcompany.brew.update.plist

Saving output from jobs run by launchd

By default, launchd saves output from scheduled programs to /dev/null. If a user wants to keep the output somewhere, which I thought would probably be a pretty good idea for brew updates/upgrades, they need to specify a location and file to save the information, commonly called a log.

For Example:

Guest on Zeus command 931 : mkdir /Users/Guest/homebrew
Guest on Zeus command 932 : cd /Users/Guest/homebrew
Guest on Zeus command 933 : touch update.log
Guest on Zeus command 934 : touch upgrade.log

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