As (somewhat*) recently mentioned I switched back to Taskwarrior. On my server I just re-enabled my cronjob to rollover incomplete tasks each day. On my work macOS machine I was doing this manually to start with until I found time to figure out launchd
(it had been a few years). I ended up with this:
<?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.taskwarrior.rollover</string>
<key>Program</key>
<string>/Users/simon/bin/task_rollover</string>
<key>StandardOutPath</key>
<string>/tmp/task.out</string>
<key>StandardErrorPath</key>
<string>/tmp/task.err</string>
<key>WorkingDirectory</key>
<string>/Users/simon</string>
<key>UserName</key>
<string>simon</string>
<key>RunAtLoad</key>
<false />
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>0</integer>
<key>Minute</key>
<integer>1</integer>
</dict>
</dict>
</plist>
And not that I needed to for this case, but if you want to run at multiple times then you need to use array
:
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>09</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>22</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>
(I needed this kind of setup for something else, but might as well include it in these notes/post).
Anyway, the script I was calling was just:
#!/bin/sh
/opt/pkg/bin/task $(/opt/pkg/bin/task rc:/Users/simon/.taskrc status:pending due.before:today ids) rc:/Users/simon/.taskrc rc.confirmation:no rc.bulk:100 modify due:today
I couldn’t figure out getting it working without a wrapper script.
Also, to get it to actually load and run properly I couldn’t use the (deprecated?) load
/unload
commands:
launchctl load ~/Library/LaunchAgents/org.taskwarrior.rollover.plist
launchctl unload ~/Library/LaunchAgents/org.taskwarrior.rollover.plist
I had to do:
launchctl enable user/501/~/Library/LaunchAgents/org.taskwarrior.rollover.plist
launchctl bootstrap gui/501 ~/Library/LaunchAgents/org.taskwarrior.rollover.plist
The 501
you can get from running id
. Then you should see the launchagent listed via launchctl list
.
To run it once:
launchctl kickstart gui/501/org.taskwarrior.rollover
To disable:
launchctl disable user/501/~/Library/LaunchAgents/org.taskwarrior.rollover.plist
launchctl bootout gui/501 ~/Library/LaunchAgents/org.taskwarrior.rollover.plist
You need to disable and re-enable if you make changes to the plist file. I like how Apple streamlined that from two unload
and load
commands to needing four commands. Thanks to stumbling across this Reddit post for those.
Also, the StandardOutPath
and StandardErrorPath
didn’t actually help at all with debugging why it wasn’t running so those can be removed.
Give me the simplicity of NetBSD’s cron any day.
* - I wrote this up ages ago and forgot to post it