[Chapter 40] 40.12 Periodic Program Execution: The cron Facility
Author: Jerry Peek, Tim O'Reilly & Mike Loukides
Date: 1998-08-04T21:50:42Z

#

| Chapter 40 Delayed Execution |

## 40.12 Periodic Program Execution: The cron Facility

cron allows you to schedule programs for periodic execution. For example, you can use cron to call a particular UUCP (1.33) site every hour, to clean up editor backup files every night, or to perform any number of other tasks. However, cron is not a general facility for scheduling program execution off-hours; use the at command (40.3).

With redirection (13.1), cron can send program output to a log file or to any username via the mail system (1.33).

> NOTE: cron jobs are run by a system program in an environment that's much different from your normal login sessions. The search path (8.7) is usually shorter; you may need to use absolute pathnames for programs that aren't in standard system directories. Be careful about using command aliases, shell functions and variables, and other things that may not be set for you by the system.

### 40.12.1 Execution Scheduling

The cron system is serviced by the cron daemon (1.14). What to run and when to run it are specified to cron by crontab entries, which are stored in the system's cron schedule. Under BSD, this consists of the files /usr/lib/crontab and /usr/lib/crontab.local; either file may be used to store crontab entries. Both are ASCII files and may be modified with any text editor. Since usually only root has access to these files, all cron scheduling must go through the system administrator. This can be either an advantage or a disadvantage, depending on the needs and personality of your site.

Under System V (and many other versions of UNIX), any user may add entries to the cron schedule. crontab entries are stored in separate files for each user. The crontab files are not edited directly by ordinary users, but are placed there with the crontab command (described later in this section). [In my experience, the cron jobs are run from your home directory. If you read a file or redirect output to a file with a relative pathname (14.2), that'll probably be in your home directory. Check your system to be sure. -JP ]

crontab entries direct cron to run commands at regular intervals. Each one-line entry in the crontab file has the following format:

> mins hrs day-of-month month weekday username cmd (BSD)
> mins hrs day-of-month month weekday cmd (System V)

Spaces separate the fields. However, the final field, cmd, can contain spaces within it (i.e., the cmd field consists of everything after the space following weekday); the other fields must not contain spaces. The username field is used in the BSD version only and specifies the username under which to run the command. Under System V, commands are run by the user who owns the crontab in which they appear (and for whom it is named).

The first five fields specify the times at which cron should execute cmd. Their meanings are described in Table 40.1.

Table 40.1: crontab Entry Time Fields
Field | Meaning | Range
--- | --- | ---
mins | The minutes after the hour. | 0-59
hrs | The hours of the day. | 0-23 (0 = midnight)
day-of-month | The day within a month. | 1-31
month | The month of the year. | 1-12
weekday | The day of the week. | 1-7 (1 = Monday) BSD
|  | 0-6 (0=Sunday) System V

These fields can contain a single number, a pair of numbers separated by a dash (indicating a range of numbers), a comma-separated list of numbers and ranges, or an asterisk (a wildcard that represents all valid values for that field).

If the first character in an entry is a hash mark (#), cron will treat the entry as a comment and ignore it. This is an easy way to temporarily disable an entry without permanently deleting it.

Here are some example crontab entries (shown in System V format):

    2>&1

    \%
    0,15,30,45 * * * *  (echo -n '   '; date; echo "") >/dev/console
    0,10,20,30,40,50 7-18 * * * /usr/lib/atrun
    7 0 * * *  find / -name "*.bak" -type f -atime +7 -exec rm {} \;
    12 4 * * *  /bin/sh /usr/adm/ckdsk >/usr/adm/disk.log 2>&1
    22 2 * * *  /bin/sh /usr/adm/ckpwd 2>&1 | mail root
    30 3 * * 1 /bin/csh -f /usr/lib/uucp/uu.weekly >/dev/null 2>&1
    12 5 15-21 * * test `date +\%a` = Mon && /usr/local/etc/mtg-notice
    #30 2 * * 0,6  /usr/lib/newsbin/news.weekend

The first entry displays the date on the console terminal every fifteen minutes (on the quarter hour); notice that multiple commands are enclosed in parentheses in order to redirect their output as a group. (Technically, this says to run the commands together in a subshell (13.7).) The second entry runs /usr/lib/atrun every ten minutes from 7:00 a.m. to 6:00 p.m. daily. The third entry runs a find command at seven minutes after midnight to remove all .bak files not accessed in seven days. [To cut wear and tear and load on your disk, try to combine find jobs (23.22). Also, as article 40.5 explains, try not to schedule your jobs at often-chosen times like 1:00 a.m., 2:00 a.m., and so on; pick oddball times like 4:12 a.m. -JP ]

The fourth and fifth lines run a shell script every day, at 4:12 a.m. and 2:22 a.m., respectively. The shell to execute the script is specified explicitly on the command line in both cases; the system default shell, usually the Bourne shell, is used if none is explicitly specified. Both lines' entries redirect standard output and standard error, sending it to a file in one case and mailing it to root in the other.

The sixth entry executes a C shell script named uu.weekly, stored in /usr/lib/uucp, at 3:30 a.m. on Monday mornings. Notice that the command format - specifically the output redirection - is for the Bourne shell even though the script itself will be run under the C shell. The seventh entry runs on the third Monday of every month; there's more explanation below. The final entry would run the command /usr/lib/newsbin/news.weekend at 2:30 a.m. on Saturday and Sunday mornings if it were not disabled with a `#`. (`#` can also be used to add comments to your crontab.)

The fourth through sixth entries illustrate three output-handling alternatives: redirecting it to a file, piping it through mail, and discarding it to /dev/null (13.14). If no output redirection is performed, the output is sent via mail to the user who ran the command.

The cmd field can be any UNIX command or group of commands (properly separated with semicolons). The entire crontab entry can be arbitrarily long, but it must be a single physical line in the file.

One problem with the crontab syntax is that it lets you specify any day of the month, and any day of the week; but it doesn't let you construct cases like "the third Monday of every month." You might think that the crontab entry:

>     12 5 15-21 * 1 your-command

would do the trick, but it won't; this crontab entry runs your command on every Monday, plus the 15th through the 21st of each month. [1] An answer from Greg Ubben is shown in the seventh entry. He uses the test (44.20) and date (51.10) commands to compare the name of today (like Tue) to the day we want the entry to be executed (here, `Mon`). This entry will be run between the 15th and 21st of each month, but the mtg-notice command will only run on the Monday during that period. The shell's `&&` operator (44.9) runs the mtg-notice command only when the previous test succeeds. Greg actually writes the entry as shown here, testing for failure of the test command:

> [1] This strange behavior seems to be a System V peculiarity that somehow infected the rest of the world. "True" BSD systems behave the way we explained earlier. However, SunOS 4.X systems have incorporated System V's behavior; and, with the advent of Solaris, there are relatively few true commercial BSD systems left in the world.

>     12 5 15-21 * * test `date +\%a` != Mon || /usr/local/etc/mtg-notice

He did it in that "backwards" way so the cron job's exit status would be 0 (success) in the case when it doesn't execute mtg-notice. You may need that technique, too.

The cron command starts the cron program. It has no options. Once started, cron never terminates. It is normally started automatically by one of the system initialization scripts. cron reads the crontab file(s) every minute to see whether there have been changes. Therefore, any change to its schedule will take effect within one minute.

- AF, JP

40.11 Send Yourself Reminder Mail |  | 40.13 Adding crontab Entries