You can print the StartCalendarInterval dictionaries with something like this: for h in {0..4}; do for m in {0,15,30,45}; do echo "<dict><key>Hour</key><integer>$h</integer><key>Minute</key><integer>$m</integer><key>Second</key><integer>0</integer></dict>"; done; done
.
You could also run the script every 15 minutes but exit it depending on the time:
h=$(date +%-H)
m=$(date +%-M)
[[ $h -gt 4 || $h -eq 4 && $m -ne 0 ]] && exit
Or run EDITOR=nano crontab -e
and add a line like */15 0-4 * * * ~/bin/script
.
The Program
key specifies the file to execute, & the ProgramArguments
key specifies the arguments which will be passed to the executing process. Strictly speaking you can pass whatever arguments you want to a process, but the convention is that the first one should be the name by which the process was invoked, so most programs ignore their first argument.‡ The file to execute is obviously necessary information, but if the Program
key is is missing, launchd pretends it has the same value as the first argument in ProgramArguments
purely as a convenience.
Your first example starts boinccmd & gives it arguments that would be equivalent to the terminal command
--host\ localhost --passwd\ gobbledygook --project\ http://setiathome.berkeley.edu/\ update
which tells boinccmd that you invoked it as "--host localhost" & only passed it two weird arguments.
Your second example separates the arguments correctly, but as Eddie Kelley suggested it needs one inserted at the front. It tells boinccmd that you invoked it as "--host", then passed another six arguments. boinccmd can recognise the last five as being two options, but has no idea what the "localhost" business is about. As far as boinccmd can tell, it was invoked from the terminal as
/Library/Application\ Support/BOINC\ Data/boinccmd localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update
(note the missing "--host").
boinccmd is probably one of the great majority of programs that don't care what their first argument is, so you could probably actually just shove <string>HELLO</string>
at the head of the ProgramArguments
array, but it's probably cleaner to remove the Program
key altogether & just use this:
<key>ProgramArguments</key>
<array>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<string>--host</string>
<string>localhost</string>
<string>--passwd</string>
<string>gobbledygook</string>
<string>--project</string>
<string>http://setiathome.berkeley.edu/</string>
<string>update</string>
</array>
‡ It can seem like a meaningless redundancy, but some programs use this to good effect: bash et al. act as login shells if their first argument begins with -
, & Vim enters various emulation modes if its first argument is ed
or vi
instead of vim
.
Best Answer
The "standard" thing to do is make a new .plist for each different time/argument combo. This is essentially the equivalent of making multiple entries in the crontab, except that each "entry" is an entire file, not just a line.
There's a good example of this in macOS's launch daemon entries for the periodic maintenance program. /System/Library/LaunchDaemons/com.apple.periodic-daily.plist runs /usr/libexec/periodic-wrapper with the argument "daily" and a 24-hour interval, ...periodic-weekly.plist runs it with the argument "weekly" and a 7-day interval, and ...periodic-monthly.plist runs it with the argument "monthly" and a 30.44-day interval.