The primary tool for scheduling tasks on the command line is the venerable cron
. This tool is started automatically by launchd
(as required) and runs continuously in the background. When loaded, cron
wakes up every minute to consult a set of tables to see if there is anything to be executed at that time. If so, it takes care of executing it. These tables, known as crontab
files, are located in two places on the filesystem:
/etc/crontab
The crontab
file for the system at large. Each entry in this table represents a command that will be run by the root
user and the time that it will be run. Anybody can read this file, but only the root
user can edit it. Starting in Tiger, most of the tasks that were once launched by cron
have made their way to launchd
. Thus, crontab
is somewhat deprecated from Apple’s standpoint, but it’s still there if you want it.
/var/cron/tabs/
This directory contains the user crontab
files for each user on the system who is using cron
. These files are hidden and are visible only to the root
user, so that other users on the system can’t look at each other’s crontab
files.
The launchd
daemon loads cron
only if a crontab
is set up on the system. In a default Tiger install, this means cron
is not running at all. However, once you install a crontab
for your user or make changes to the system crontab
, launchd
notices the change and launches cron
.
The crontab
file format is similar to that of many other Unix utilities. Any line beginning with the hash character (#
) is a comment. Each entry in a crontab
file consists of five numbers defining the time pattern at which a particular task is to run. The end of the line contains the command to run. In the case of the system crontab
, the command also contains the name of the user under which to run the command. Figure 13-3 describes the settings for each of these fields. In addition to numbers, each field can contain an asterisk (*
) character, which means match every possibility for that field.
For each of the fields, you can also specify a list or range of numbers. For example, if you wanted to run a command every 15 minutes, you could use the following line:
0,15,30,60 * * * * command
Or, if you wanted a command to only run at 5:00 p.m. on weekdays, you could use the following:
0 5 * * 1-5 command
To set up tasks that will get executed, you have to edit your own personal crontab
. You can take a look at what you already have in your crontab
file by using the crontab
command:
$ crontab -l
crontab: no crontab for jldera
This output means nothing has been scheduled yet. By default, a user account won’t have a crontab
when it is first set up.
There are two ways to edit your crontab
. The first involves using whatever editor you’ve set up on the command line (for example, vi
, Emacs, and nano
). The second involves using any editor you want (such as TextEdit or BBEdit) and loading a text file as your crontab
. To edit your file on the command line, use the following command:
$ crontab -e
For your first crontab
entry, let’s add a line that will make your computer say “hello” every minute. To do this, add the following line to your crontab
file:
* * * * * osascript -e 'say "hello"'
If you get stuck in an editor that you are unfamiliar with, remember that you can get out of vi
by typing :q!
and out of Emacs by typing Control-X then Control-C. See Chapter 4 for more info about command-line editors.
Now, every minute of every day that your machine is on, it will say “hello” to you, which could become annoying indeed. There are a couple things going on here:
The osascript -e 'say "hello"'
command is being issued by your system every minute, based on the five preceding asterisks.
The command uses the default system voice set in the Speech preference panel to speak the word “hello” on cue.
But now that you’ve got a crontab
file installed, you can use crontab
to list the file:
$ crontab -l
* * * * * osascript -e 'say "hello"'
The other way to create a crontab
file is to use an editor like TextEdit or BBEdit. To get the current crontab
out in a form that you can open with any editor, save the file on your hard drive, and then execute the crontab
command as follows:
$crontab
mycrontabfile
This also gives a way to quickly reset the crontab
file for a user. By passing the /dev/null
file into crontab
, the user’s crontab
will be set to an empty file.
Using the crontab
command to specify a file is also a good way to accidentally lose any cron
settings that you have in place. Be sure to check your crontab
before loading in a new crontab
file.
To retrieve your crontab
for editing, you can direct the output using the following command:
$crontab -l >
mycrontabfile
Finally, if you want to get rid of your crontab
altogether, enter the command:
$ crontab -r
The cron
command on Mac OS X has been enhanced compared to those found on some other Unix variants. For example, you can use the following more readable entries in the time field:
Days of the week can be indicated by their abbreviated names: sun
, mon
, tue
, wed
, thu
, fri
, or sat
.
Months can be indicated by their abbreviated names: jan
, feb
, mar
, apr
, may
, jun
, jul
, aug
, sep
, oct
, nov
, or dec
.
You can indicate step values by using a fraction notation such as 8-17/2 which, if it were in the hours field, would mean “every two hours between the hours of 8 a.m. and 5 p.m.”
Some special strings can be used in crontab
files. Table 13-1 has a list of these strings. Except for the last one, all these strings replace the time fields. The last, @AppleNotOnBattery
, can be used in front of a command to prevent it from running when your laptop is disconnected from AC power. This ensures that you don’t run disk-intensive tasks when you need your battery the most. For example, if you write a script that copies all your files from your ~/Documents
folder to some safe storage location that you want to run only when your PowerBook is plugged in, you would use the following crontab
entry:
0 * * * * @AppleNotOnBattery ~/bin/copyfiles
Table 13-1. Special strings that can be used in a crontab
String |
Description |
Equivalent to |
---|---|---|
@reboot |
Runs when the system reboots | |
@yearly |
Runs at midnight of January 1 |
0 0 1 1 * |
@monthly |
Runs at midnight on the first of the month |
0 0 1 * |
@weekly |
Runs at midnight each Sunday |
0 0 * * 0 |
@daily |
Runs every day at midnight |
0 0 * * * |
@hourly |
Runs every hour at the top of the hour |
0 * * * * |
@AppleNotOnBattery |
Prevents command from running if the system is on battery |
The cron
system won’t execute while your system is asleep. This is because the CPU is powered down and there’s just enough happening in your machine to keep the contents of memory ready when you want to wake the system up.
Sometimes this isn’t a big deal. For example, if you use a crontab
line to remind you to stretch every hour, then you won’t mind it not running. However, for other tasks that you would like to have run, it can create a bit of a problem. The best piece of advice is to time tasks that need to be run when your system is less likely to be in sleep mode.