How can I get a script to run every day on Mac OS X?
Cron? Launchd? iCal??
If so, how?
For reference, all 3 options would work. The iCal option however has more limitations than the others.
(There are GUIs for editing cron and launchd as mentioned in other answers)
Cron is the most straight forward and well known and there are many tutorials available. The Coles Notes is to add the last line from below to your crontab (either by editing /etc/crontab
or using crontab
on the command line):
MM HH DD MM WKD -- Minutes, Hour, Day, Month, Weekday (eg. Sun, Mon)
MM HH * * * USERNAME /PATH/TO/SCRIPT
00 3 * * * chealion /myscript.sh "Runs at 03:00 every day"
In Mac OS X, cron
has actually been replaced by launchd
but launchd
is backwards compatible with cron
meaning you can still use cron
but it's actually launchd
doing all the work.
If you want to use launchd
you'll want to check out other questions here on Super User as well: (eg. How do I run a launchd command as root?) as to where you want to save your configuration file (the plist file) as when it runs depends on what directory it is stored in and how it's loaded (eg. whether you used sudo or not) - similar to cron.
A sample run daily launchd plist (be sure the file and and the label are the same - minus the plist for the label) follows - this script is run everyday at 3 minutes past midnight:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.IDENTIFIER_HERE.SOMETHING</string>
<key>KeepAlive</key>
<false/>
<key>RunAtLoad</key>
<false/>
<key>UserName</key>
<string>USERNAME HERE</string>
<key>Program</key>
<string>/PATH/TO/SCRIPT</string>
<key>ProgramArguments</key>
<array>
<string>Argument_1</string>
<string>Argument_2</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>00</integer>
<key>Minute</key>
<integer>03</integer>
</dict>
</dict>
</plist>
It's also worth noting that launchd tasks if they were scheduled for when the computer is asleep or off, they will run when the computer becomes available again (turning it on or waking it up) - though only once no matter how many days it may have been. Edit: I just was at an Apple document that said that if the machine is off, then you will lose any launch events during that time, (your script will not launch on startup), (sleep does launch script on waking up)
Another option is to use "at" (check manual page with "man at"). The script can reschedule itself with e.g.:
echo "sh $0 $@" | at `date +%H:%M` tomorrow
(use "+ 10 minutes" instead of "tomorrow" to run it every 10 minutes; to stop scheduling, just do "at -l" to list the scheduled job ids and then "at -r id" to remove the job)
You may have to start the corresponding daemon (atrun) first with (see https://superuser.com/a/43680):
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
Advantages: quick fix, no sudo/root access needed, easy to do complicated schedule patterns Disadvantage: not standard scheduling method for OS X (which is launchd)
LaunchControl is another GUI for launchd/launchctl. While the alternatives mentioned by others are perfectly capable of launching a script on a daily basis, with LaunchControl you can configure complex schedules (like "once every weekday, on weekends every hour between 2PM and 8PM"). Also it is (AFAIK) the only tool which actually validates the job. If a job does not work as expected it will show you why.
It's free to try for as long as you want.