The cron utility runs continuously in the background, taking care of scheduled system tasks and user requests at the appropriate time.
You might not know it, but your Mac does quite a bit on its own behind your back ? or under your fingertips, I should say. Your system regularly purges itself of outdated, space-hogging log files, updates system databases so utilities like locate (type man locate on the command line for details) can work effectively, and performs several other maintenance tasks that keep your system running lean and mean.
It does so by means of a task-scheduling utility called cron (as in chronological). The cron command launches automatically at system startup and runs continuously in the background. It keeps a list of what needs to happen when and consults this list each and every minute of each and every day, at least while your machine is awake. When it notices it's time to perform some duty, it does so quietly in the background.
The lists are kept in crontab files associating a particular action with a timetable. Each user account can have its own crontab file. The system itself has a special crontab, found in the /etc directory; it belongs to the superuser, or root, account and takes care of actions requiring the kind of system access allowed only to root [Hack #50].
The format of a crontab file might appear rather esoteric at first, but it's really rather simple. For example, Figure 5-20 shows the system's crontab for carrying out regular maintenance. The numbers in the circled area specify the time cron runs the scripts (there are actually three of them).
Each of the three lines (numbered 1, 2, and 3 in Figure 5-20) specifies one of the three scripts the system's cron runs by default. Each script is different, performing its own appropriate set of maintenance procedures. The daily script, on the line labeled 1, runs once each day. The weekly script, specified on line 2, runs once each week. And the monthly script, specified on line 3, runs ? you guessed it ? once each month.
The first five columns or fields of each line specify at exactly which interval the script will run. The fields specify, from left to right, the minute, hour (on a 24-hour clock), day of the month, month, and weekday (either short versions, MON-FRI, or numerically, with Sunday as 0 or 7). An asterisk instead of a number in a field means "every."
For example, line 1 specifies a time of 3:15 a.m.:
15 3 * * * root periodic daily
Since the rest of the columns contain asterisks, the daily script will run at 3:15 a.m. on every day of the month, every month, and every day of the week ? that is, every day at 3:15 a.m.
Line 2 specifies that the weekly script runs at 4:30 a.m. on every weekday number 6, or Saturday:
30 4 * * 6 root periodic weekly
And line 3 specifies that the monthly script runs at 5:30 a.m. on day 1 (the first) of each month:
30 5 1 * * root periodic monthly
That's about all there is to it.
As I mentioned, you have your own personal crontab with which to have the system automatically and regularly do your bidding. To take a gander at what you've already got scheduled, open a Terminal [Hack #48] window and type: crontab -l (that's l as in list):
% crontab -l crontab: no crontab for rael
If, like me, you've not yet scheduled anything, crontab -l doesn't produce anything particularly remarkable. Let's change that by editing your crontab and adding something interesting.
Before doing so, you should set your default command-line editor [Hack #51] so that the file opens in an editor you can use. The crontab command uses this editor to edit its files. Here, I set my editor to pico and open up my crontab:
% setenv EDITOR /usr/bin/pico % crontab -e
The -e option, as you might have guessed, stands for edit. pico launches and I'm editing an as-yet-empty text file. Don't worry about what file it is or where it lives; crontab takes care of all those details for you.
Using the guidelines explained earlier in The crontab File, let's add a reminder to exercise at 4:00 p.m. every weekday. The only difference is that the who field (see Figure 5-20) doesn't apply, since this crontab already belongs to someone ? you:
#minute hour mday month wday command 0 16 * * mon-fri /usr/bin/osascript -e 'say "time to get your lazy RETURN butt off that chair and do some exercise."'
I've taken the liberty of copying the comment from the system's crontab (removing the who field) to remind me what goes where. Any line prefixed with a # (hash or pound sign) is treated as a comment for a human reader's information only and is ignored.
Each entry should be contained on one line. The previous example is split only for presentation purposes and would not run. It's generally better form to push long commands out to a script and just invoke the script via cron. I might put that AppleScript invocation into a file called exercise.sh in a bin directory in my home directory:
#!/bin/sh /usr/bin/osascript -e 'say "time to get your lazy butt off that chair and do some exercise."'
I'd make it executable [Hack #49] (chmod u+x exercise.sh) and alter my crontab appropriately:
#minute hour mday month wday command 0 16 * * mon-fri /Users/rael/bin/exercise.sh
The nice thing about cron ? in this case ? is that it doesn't run when the computer's asleep or shut down; it'll remind me to exercise only when I'm working at four in the afternoon, Monday through Friday.
Apple has preconfigured the system's crontab to automate various tasks you wouldn't know to do in the first place. The not-so-good news is that they've scheduled these groups of tasks to run between 4:00 and 5:00 in the morning ? a time when your Mac is likely not even on! And if your Mac is never on during these times, these important tasks will never happen. If your Mac is powered on but in deep sleep, the jobs still won't run.
Let's modify the system's schedule slightly so that these tasks occur at more reasonable times. Of course, what counts as reasonable depends on your own situation, so consider these factors when deciding:
Choose a time when your Mac is likely to be on (and not asleep).
Choose a time when a few minutes of background activity won't disturb your work too much. On faster machines the activity is hardly noticeable, but it could cause some stuttering if, for example, you happened to be watching a DVD at the time.
Choose a time that is unique for each script. You don't want to schedule scripts to run at the same time.
For example, these times might be good for a machine that's on only during normal work hours:
Every day at 4:15 p.m.
Every Monday at 9:50 a.m.
The first of every month at 10:30 a.m.
Regarding the monthly job, the first of the month sometimes falls on a weekend or holiday, but for now that's the best you can do.
To modify the system's crontab file to reflect these new times, you'll need to open it up in pico, edit it, and save it yourself since the jobs don't belong to one user in particular, rendering crontab -e inapplicable.
% sudo pico /private/etc/crontab
First, change the 3 in the daily script line to 16:
15 16 * * * root periodic daily
Next, change the time in the weekly script line as shown here:
50 8 * * 2 root periodic weekly
Finally, change the time in the monthly script line:
30 10 1 * * root periodic monthly
Once you've made the changes, save (write out) the document by pressing Control-O. You'll then be prompted to confirm the save; just press Return to do so. Finally, quit pico by pressing Control-X.
Once you've saved the crontab file, the new scheduling takes effect immediately; there's no need to restart.