For one-time jobs (scheduled tasks), at
commands are simple to schedule, as demonstrated by John1024's since-deleted answer, but at
has drawbacks on OSX:
- It must be enabled first; this is a one-time operation:
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
.
- You must use
sudo
(have administrative privileges) to be able to schedule job with at
.
- If a job produces any output, it will be mailed to the user using
mail
, as stdout and stderr output (I don't know how to suppress this).
- Example: schedule opening http://stackoverflow.com once, at 19:00 (7 PM):
sudo bash -c 'echo "open http://stackoverflow.com" | at 19:00'
Using crontab
for periodic jobs is an option on OSX; e.g., to schedule a job that opens http://stackoverflow.com every day at 19:00 (7 PM):
- Run
crontab -e
to open the current user's cronfile in your editor.
- Add the following line, save, and close the file:
0 19 * * * open http://stackoverflow.com
- If a job produces any output, it will be mailed to the user using
mail
, as combined stdout and stderr output (I don't know how to suppress this).
However, the official recommendation on OSX is to use launchd
for both one-time and periodic jobs:
launchd
is very flexible and centralizes all job scheduling; as with crontab
, there are system-wide and per-user jobs.
- the downside is that the
.plist
files required to define jobs are cumbersome and non-trivial to create.
Using our previous example:
One-time job: (opens http://stackoverflow.com once, at 19:00 (7 PM))
- Create file
~/test.plist
(for a one-off job, the location doesn't matter).
- Paste the following:
<?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>TestJob</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>http://stackoverflow.com</string>
</array>
<key>LaunchOnlyOnce</key>
<true/>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>19</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
</dict>
</plist>
TestJob
uniquely identifies your job.
- Setting
LaunchOnlyOnce
to true
ensures that the job is only run once.
- From Terminal, run
launchctl load ~/test.plist
to load the job.
Periodic job: (opens http://stackoverflow.com every day at 19:00 (7 PM))
- Create file
~/Library/LaunchAgents/testPeriodic.plist
- Note: The location matters:
~/Library/LaunchAgents
is where per-user job-definition *.plist
files must reside in order to be loaded automatically at every logon.
- Paste the following:
<?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>TestJobPeriodic</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>http://stackoverflow.com</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>19</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
</dict>
</plist>
- Again,
TestJobPeriodic
uniquely identifies your job.
- Jobs runs periodically by default (i.e., the absence of
LaunchOnlyOnce
makes the job periodic).
- From Terminal, run
launchctl load ~/Library/LaunchAgents/testPeriodic.plist
to load the job.
For background information, see https://stackoverflow.com/a/23880156/45375.