Set up timed or recurring scripts

Set up timed or recurring scripts

It’s fairly straightforward to leverage launchd to run a script either at specified intervals or at specific times of the day. I find that most people only want to do fairly simple things, so I’ve kept this simple.

The way launchd works is that you create a plist, then run a command to either load or unload the plist. Here is an example plist that will run the script called “rsync-backup-work” every 3 hours. The first 3 lines are just boilerplate for 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>org.cricket.rsync-backup-work</string
<key>ProgramArguments</key>
<array>
<string>/Users/admin/bin/rsync-backup-work</string
</array>
<key>StartInterval</key>
<integer>10800</integer>
</dict>
</plist>

This has only three keys:

  • Label → Unique identifier (this can just be the name of the plist without the plist suffix to make it simple)
  • ProgramArguments → First item in the array is the path to an executable, the rest would be arguments to that executable
  • StartInterval → How often to run in seconds

Setup

  • Create plist
  • sudo mv the plist to /Library/LaunchDaemons
  • Run “launchctl load <path to plist>

To verify, run “launchctl list | grep <identifier>” and you’ll see something like this:

- 0 org.cricket.delete-crap

The first column is the PID if it’s currently running, the second is the exit code, and the third is the unique identifier you set

Extra credit

There are a number of other interesting keys you might want to insert into your plist. Note that if edit the plist, you’ll have to unload and then load the plist again. Presented as examples.

<!--
To have something repeat at 8am every day:
—>

<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>08</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
<!--
To have something run when you load the plist rather than waiting for the first interval to arrive:
—>

<key>RunAtLoad</key>
<true/>
<!--
To watch specific folders and execute something when something changes:
—>

<key>WatchPaths</key>
<array>
<string>/Users/admin/crap</string>
</array>
<!--
To log standard out and standard error to files:
—->

<key>StandardOutPath</key>
<string>/var/tmp/delete-crap-out.log</string>
<key>StandardErrorPath</key>
<string>/var/tmp/delete-crap-error.log</string> <key>Debug</key>
<true/>

More information

For information on all the keys you can put into a launchd plist:

man launchd.plist