How to setup and debug a cronjob in macOS
I was surprised to see that macOS comes with cron pre-installed. A cron job is basically a recurring scheduled task, e.g. a script or command that is run every Tuesday on 2pm. To check if there any existing cron jobs run:
$ crontab -l
crontab: no crontab for alinz - using an empty one
crontab: no changes made to crontab
Let's say I want to commit my Obsidian notes once a day. First I write a small script that contains the commit logic before I setup the cron job.
$ cat <<"EOD">~/.local/bin/commit-obsidian-notes.sh && chmod +x ~/.local/bin/commit-obsidian-notes.sh
#!/usr/bin/env bash
set -eu
pushd ~/Documents/Obsidian
git add --all
git commit -m "Obsidian notes from $(date -Idate)"
popd
EOD
Note that the script above contains quite a bit of bash magic.
It's perfectly fine to write the script file and set the executable flag in two separate commands.
Also, if you quote the delimiter in a HEREDOC
statement, like "EOD"
in the example above, then no evaluation happens in the content.
Otherwise the $(date -Idate)
would've been evaluated to 2023-04-23 in the script.
Since we have the script our only remaining step is to setup the cron job.
Cron's syntax is a bit intricate and I'd recommend to use an online tool like crontab.guru to define the desired cron schedule expression.
Running the job every day at 8pm can be expressed as 0 20 * * *
.
To define the job run crontab -e
and enter 0 20 * * * ~/.local/bin/commit-obsidian-notes.sh
.
But there's something missing which will make the cron job fail.
Cron job errors will be reported to your local mail account, yes there's a local mail account for your user account.
To read those mail just run mail
in a terminal.
You'll see the following error:
~/Documents/Obsidian ~
fatal: Unable to read current working directory: Operation not permitted
We need to give /usr/sbin/cron
full disk access in order to fix the issue.
Please let me know if there's a way to restrict access of cron
just to a particular directory.
Open system settings.app
, then Privacy & Security and under Full Disk Access click the +
button at the bottom to add /usr/sbin/cron
.
Note that you can use Cmd+Shift+G
to enter a particular location in the file select dialog (this also works in Finder).
Et voila, you now know how to setup and debug a cron job on macOS.
PS: If your git is configured to automatically sign a commit add --no-gpg-sign
to the git commit
call or otherwise the cron job will fail because it cannot unlock your signing key.