Using cron to automate maintenance

The cron subsystem schedules tasks to run any hour of the day or night, making regular upkeep a breeze


Before you start

Learn what to expect from this tutorial and how to get the most out of it.

About this tutorial

This tutorial explains how to configure and maintain cron, the job scheduler found on almost all UNIX® machines. Additionally, this lesson demonstrates just some of the many applications of cron.


Learn how to create, schedule, and manage cron jobs and how to define timetables to control job frequency, from once per minute to once per year. Additionally, learn how to limit access to cron to prevent abuse and how to use other utilities in tandem with cron to automate common maintenance tasks.


This tutorial is written for users and systems administrators of UNIX (and UNIX-like) systems. To follow this tutorial, you should have a general familiarity with a command-line shell and shell scripting. Some experience installing and configuring software on UNIX is also helpful.

System requirements

To run the examples in this tutorial, you need a UNIX computer. If you want to configure system-wide cron jobs, you also need root access. The examples shown in this tutorial are based on Vixie cron, which is used widely on modern UNIX systems, running on Ubuntu Desktop Linux® version 8.04.1. Other versions of cron are similar to Vixie; check the documentation for your UNIX system for specifics.

Open 24/7

Unlike you and me, a computer works tirelessly, applying the same vigor to every task great and small. Moreover, a computer gladly works 24 hours per day, seven days per week, including snow days and federal holidays.

The cron daemon

To leverage round-the-clock computing, though, tasks must run at all hours of the day. You could punctuate your sleep with waking interludes to log in and run this command or that on dozens of machines, or you can enjoy your 40 winks and turn the work over to the ubiquitous cron, a daemon (or perennial process) for executing commands on a schedule. From very often to every so often, cron happily minds the clock and runs jobs day or night.

Need to monitor an FTP drop-box for incoming data? Use cron to run a shell script every few minutes. Need to delete scratch files that accumulate during the day? Slate garbage collection for the middle of the night. Want to rotate your log files on a regular basis? Set a weekly agenda.

Here, you learn how to configure and maintain cron and discover its many applications. Specifically, this tutorial looks at Vixie cron, named after its author, Paul Vixie. Vixie cron is found in FreeBSD, Apple Mac OS X, most flavors of Linux, and other UNIX systems. To determine whether your system runs Vixie cron, type man cron or man crontab, and look for the attribution for Paul Vixie at the bottom.

To follow along with this article and to use cron, you should be familiar with at least one text editor, such as vi or Emacs, and have some experience with the UNIX command line, shell scripts, and shell environment variables. Further, if you want to alter the system-wide cron configuration files, you must have root, or superuser, access.

Understanding cron-ology

The cron daemon is a small subsystem of utilities and configuration files, and a flavor of cron can be found on nearly every UNIX-like system. Cron's components include the daemon itself; a collection of system-wide configuration files; a set of per-user configuration files; a utility to add, alter, and remove user configuration files; and a simple access control facility. In general, a cron configuration file or list of cron jobs is called a crontab, short for cron timetable.

  • The daemon, cron, runs continuously, checking its configuration files for changes once per minute. Cron reads the system-wide and per-user crontabs (described in the next two bullets, respectively), updates its schedule of events accordingly, and executes all commands scheduled to run in the current minute. The daemon also captures the output of each job, if any, and e-mails the result to the job's owner.
  • System-related jobs can be defined in three places: in /etc/crontab, in any file in /etc/cron.d, and in the special directories /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, and /etc/cron.monthly:
    • The primary system crontab is /etc/crontab. The file has its own unique syntax (described in the next section), and each job defined in it runs according to its own timetable (such as twice an hour or every other day) and as a specific, named user. Use /etc/crontab to schedule miscellaneous administration and maintenance tasks.
    • You can also maintain a suite of crontabs in the directory /etc/cron.d. Create a crontab to logically group commands that pertain to a specific subsystem. For example, the package for the PHP version 5 programming language installs a crontab named php5 in /etc/cron.d to periodically purge unused sessions. Files in /etc/cron.d have the same syntax as /etc/crontab, and each job runs per its unique timetable and as a particular user.
    • As an alternative, you can simply drop a shell script into one of /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, or /etc/cron.monthly to run the script once per hour, once per day, once per week, or once per month, respectively. Scripts placed here run as the superuser.
  • The collection of per-user crontabs is commonly found in /var/spool/cron/crontabs. (Peruse the documentation for your UNIX system for the exact location. Some systems keep user crontabs in /usr/lib.) However, you cannot directly edit files in that directory. Instead, you create a crontab and submit the file with the utility crontab. Managing your personal crontab is covered momentarily.
  • Finally, you can grant or deny a user access to cron with the access control lists /etc/cron.allow and /etc/cron.deny, respectively. You might deny access to a user, for example, if his or her jobs were particularly disruptive to normal operation of the system.

As you can see, you need not forego your beauty sleep to keep your machine busy in the off-hours. Identify a job, define its schedule, capture the job in an appropriate crontab, and start counting sheep. But before you doze off, let's look at the special syntax of cron files.

Working with crontabs

A crontab is simply a text file, which you can create with any number of UNIX editors. It can contain four kinds of lines: blank lines, comments, environment variable settings, and commands.

Blank lines and comments

Blank lines and spans of white space found in the file are ignored. Use both to keep your crontabs readable and well organized.

You can also use comments to document the timetable and purpose of each job. To create a comment, simply start a new line with the octothorpe (#).

Environment variables and commands

Ultimately, cron uses a shell to execute each command. You can alter or customize the behavior of the shell through environment variables.

Shell environment variables are easily set in a crontab. Simply type VARIABLE=value, replacing VARIABLE with the name of the variable and value with a value. For example, the crontab line:


specifies an ordered list of directories for the shell search path.

The cron daemon predefines five environment variables:

  • The default value for PATH is /usr/bin:/bin.
  • SHELL is preset to /bin/sh.
  • LOGNAME is initialized to the crontab's owner's user name.
  • HOME is set to the home directory of the crontab's owner, such as /home/joe.
  • MAILTO is set to the name of the crontab's owner.

To override any of these defaults or to set any variable, simply set the appropriate environment variable in the crontab.

Of course, a crontab can have any number of command lines. Each command line specifies a frequency, a user name (only if the crontab is a system crontab), and a task to run. For example, the command:

5 0 * * *   root   find /tmp -type f -empty -delete

deletes all empty files and directories from /tmp (find /tmp -type f -empty -delete) once per day at 12:05 a.m. (5 0 * * *). The job runs as root (root).

A system crontab command must specify a user name to run the task as a specific user. (Hence, you would probably find the command above in, say, /etc/crontab.) Per-user crontabs cannot specify a user name; as you might guess, cron commands for a user always run as the user. The omission of the user name is the only difference between a system and user crontab.

As always, the devil is in the details. So, let's look at the many ways you can customize a timetable.

Customizing timetables

A cron timetable allows you to run jobs every minute or at a specific minute on a specific day. The parameters for scheduling are very flexible.

Cron fields

There are five fields—like "knobs"—that you can tweak to adjust frequency: minute, hour, day of month, month, and day of week. Table 1 summarizes what you can tune in each field.

Table 1. Scheduling options for cron jobs
3Day of month1-31Unlike minute and hour, day of month is not zero based.
4Month1-12Month is not zero based, either. Additionally, instead of 1-12, you can use the first three letters of each month's name, such as jan or may.
5Day of week0-7Both 0and7 refer to Sunday. You can also use the first three letters of each day's name, such as mon or wed.

In addition to a name or number, you can use the asterisk (*) to specify "every." For instance, an asterisk in the minute position indicates every minute of the day. (There are certainly valid uses for such a high frequency, but be careful that such tasks are very lightweight and do not run for protracted periods.)

You can also use lists of values, ranges, and steps (increments) to specify many, an inclusive range of values, and an alternating range of values, respectively. You can even combine lists and ranges. A list is a comma-separated set of values. A range is a starting and an ending value, inclusive, and an optional step value.

Let's look at some examples. Each row in Table 2 contains a timetable and a description. A command is executed by cron when the minute, hour, and month of year fields match the current time and if both the day of month and day of week are restricted (that is, not *) when at least one of the two fields matches the current time.

Table 2. Example timetables for cron jobs
MinuteHourDay of monthMonthDay of weekDescription
01151,3,5,7,9,11*Run the command at 1 a.m. on the 15th of January, March, May, July, September, and November. For better legibility, you could have written the command 0 1 15 jan,mar,may,jul,sep,nov *. When specifying a list, avoid putting a space after a comma.
0-59/15****This schedule runs the command every 15 minutes.
30***wed,friThis timetable executes its command every hour, on the half-hour, on Wednesdays and Fridays only. (You can use day names and month names in lists but not in a range.)
0,300-5,17-23***Run the command on the hour and half-hour from midnight to 5 a.m. and again between 7 p.m. and 11 p.m.
0011*Run the command once per year at the stroke of midnight of 1 January.
00**0Run the command at the stroke of midnight every Sunday. This is the equivalent of once per week.
30010,20,30*6Because the day of the month and day of the week are restricted, this command runs at 12:30 a.m. every Saturday and on the 10th, 20th, and 30th day of every month, except February.

As you can see, you can express virtually any schedule using the five parameters provided. As an added convenience, Vixie cron provides shorthand for common schedules. Table 3 lists some of the choices.

Table 3. Helpful shorthand for common schedules
@rebootRun the command whenever the machine reboots.
@dailyA shorthand for once per day.
@weeklyA shorthand for once per week.
@annuallyA shorthand for once per year. You can also write this as @yearly.
@midnightRun the command once per day at midnight. A synonym for this shorthand is @daily.

If you prefer to use the shorthand, replace the first five fields of the cron command with the moniker. The following command, albeit contrived, is much simpler to get at a glance.

@daily root /usr/local/scripts/

Sample crontab commands

With the basics under your belt, let's look at some sample user crontab commands. You can certainly apply the same commands system-wide: Just remember to specify a user name after the day of week field (the fifth field) in all system crontab entries.

Create a personal crontab

To use a personal crontab, create a file for your commands with any text editor. By convention, personal crontab files are kept in ~/.crontab, but you can name the file anything you like.


# Every day, print and delete all temporary files whose names begin with '.#'
@daily      find $HOME -type f -name '.#*' -print -delete
# Every week, show me what is consuming space in my home directory
@weekly     du -sh $HOME

Submit the personal crontab to the crontab utility

After editing your file—say, ~/mycrontab—submit it to cron with the aptly named crontab utility:

% crontab ~/mycrontab

View what's stored in cron

To see what's stored in cron, type crontab -l:

% crontab -l
# Every day, print and delete all temporary files whose names begin with '.#'
@daily      find $HOME -type f -name '.#*' -print -delete

# Every week, show me what is consuming space in my home directory
@weekly     du -sh $HOME

Replace your crontab

You can use the crontab utility to replace your crontab at any time. Simply submit a new file or a revision of the same file. To remove your crontab jobs, type crontab -r:

% whoami
% crontab ~/mycrontab
% crontab -l

% crontab -r
% crontab -l
crontab: no crontab for joe

Alternatives to cron

As useful as cron is, there are a couple of alternatives that you should be aware of.


If your system is often off or in hibernation—for example, if you use a UNIX laptop—consider adding anacron to your system. Anacron is similar to cron in that it schedules jobs to run in the future; but unlike cron, anacron run jobs even if the job's scheduled time has passed.

For example, if you scheduled a file-system backup to run Sunday but the system is switched off from Friday to Monday, anacron runs the Sunday job as soon as the system is reactivated on Monday. In contrast, cron merely checks whether a job is to run right now; hence, if the system is off when the job is scheduled, the job doesn't run.

Anacron has far fewer scheduling options than cron. It can only schedule jobs in whole-day intervals, such as one, seven, or 30 days, but it's a better choice for jobs that must run frequently and reliably.

Also, you must launch anacron from cron. Each time anacron runs, it reads its own configuration file consisting of pairs, where each pair is a job and its frequency expressed in days. If a job hasn't run in its period, anacron runs the job and notes the time the job ran. When all jobs finish running, anacron exits.

Anacron is available on most Linux distributions, but you can also easily download and build the source code yourself. Visit the anacron project page to get the latest release.

The anacron primary configuration file can be found in /etc/anacron. You can set environment variables just as you do with cron, but its entries are simpler:

# format: frequency delay name job
1 10 day-to-day

The first number is the period, so 1 means run once every day. A 7 would mean run once per seven days, and so on. The second number is the delay, which is the number of minutes to wait after anacron launches to start this job. The delay field, if set to distinct values, prevents all jobs from starting at the same time. The name day-to-day is just a helpful nickname. The rest of the line specifies the job; here, the shell script, found in one of the directories in the named path, runs every day.

Anacron has good documentation in the form of man pages, and you can find very good tips on anacron on the Web. (Check out Rod Smith's Linux Magazine article, which I edited in October 2007.) Anacron is ideal for UNIX road warriors or for any systems administrator who wants a bit of extra insurance.

Launchd: A modern alternative to cron

Cron is certainly a capable and venerable utility, as evidenced by its widespread usage. Recent additions in Vixie cron, such as shorthand for @reboot, make it even easier to administer. However, cron does have some shortcomings:

  • Although cron jobs are defined in crontab files, you cannot start and stop a cron job from the command line. Moreover, you cannot create an ad hoc job at the command line and submit it to the calendar.
  • Cron does not enforce resource limits. A job can consume innumerable cycles and memory if run as root. You may, instead, want to damp down a job so that it cannot interfere with other cron jobs and the overall quality of system operations.
  • Cron jobs adhere rigidly to a schedule. There is no way, for instance, to have a job launch only when an event occurs, such as the creation of a file.
  • In a larger context, UNIX-like systems have many core components capable of launching other programs on demand, including cron, xinetd (or inetd) for networking daemons, and init, the progenitor of all system processes. Each core component has its own set of configuration files, making it difficult to know which components to tailor to make a change.

To address these shortcomings, Apple Computer created a unified launch facility, aptly named launchd, to start processes on boot, on demand, and at specified intervals. In fact, launchd replaced cron (and init and several other system utilities used to boot and initialize the system) in Mac OS 10.4 Tiger. (Apple left cron on the system, though as a convenience and because Vixie cron has more flexible scheduling options.) Indeed, the phenomenal boot speed of Mac OS X can be attributed to launchd: It enumerates what to launch at boot but executes the programs only when first needed.

To date, launchd has been ported to FreeBSD but not to other UNIX or Linux systems. However, various projects are actively implementing the equivalent of launchd, so a brief survey of its features is necessary:

  • Rather than create a job to poll a directory for new files, launchd can automatically monitor a directory for new files or monitor an empty directory for any files and launch your job on demand. Launchd does not poll; instead, it uses the kqueues facility to have the kernel alert it when a directory is changed. (Linux has a similar event facility called inotify, which will be covered in a separate developerWorks article in the coming months.)
  • If specified, launchd uses chroot to send your job to a new directory. Pronounced "cha-root," chroot is a system call to change the directory that the forward slash (/) and the root directory point to. Thus, if you use chroot to send the file to /opt/root, all files outside /opt/root are inaccessible—after all, /opt/root is now /, the top-level directory of the file system—and all directories within /opt/root become top-level directories. You most commonly use chroot to secure jobs so that code cannot wander into the larger file system to wreak havoc.
  • You can set resource limits for a job. Resources you can constrain include memory, stack size, and the maximum number of open files.
  • When a task is defined and loaded into launchd, you can start and stop the job by name from the command line.

Launchd is made of three components: the launchd daemon itself; the launchctl utility used to add, alter, and remove jobs and affect launchd; and one or more configuration files, where each file defines one or more jobs. Given its origin on Mac OS X, launchd configuration files are simply properties files, which can be expressed as Extensible Markup Language (XML).

Briefly, here is how you would use launchd on Mac OS X—say, to monitor a directory for incoming files and run a job on demand:

  1. Create a properties file to express the job and all its attributes.

    You can use the Mac's Property Editor, or you can edit the XML by hand. In either case, the resulting file looks something like Listing 1.

    Listing 1. A sample launchd job to monitor a file system directory for changes
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 
                1.0//EN" "">
    <plist version="1.0">

    In a nutshell, this file runs the utility script found in /Users/strike/bin/processor whenever the contents of the directory /Users/strike/data/incoming changes. Setting OnDemand to True tells launchd to start this job as needed. Save the file to ~/Library/LaunchAgents/com.example.processor.plist.

  2. Load the job into launchd with launchctl:
    % launchctl load ~/Library/LaunchAgents/com.example.processor.plist

    If you want to verify the last operation or see your list of saved jobs, simply type launchctl list.

  3. To remove a job, again use launchctl with unload:
    % launchctl unload -w ~/Library/LaunchAgents/com.example.processor.plist

    What does -w do? It removes the job from launchd completely. Without it, the job would re-load automatically at login (because the job is in the per-user collection of launch agents).

The launchd man pages have lots of information, and if you're a Mac OS X user, you can find any number of applications for launchd. Hopefully, some clever developer will port launchd more widely.

Using cron to your advantage

Get a few tips and tricks for using cron, and discover why this daemon and others like it may just be your best friends.

Tips and tricks

Here are some tips, tricks, and common pitfalls of cron:

  • Unlike the shell you use in a terminal window or for a shell script, crondoes not expand environment variables in-place in crontab files. In other words, if you place the lines:

    in a crontab, PATH is not set to what you expect. Instead, you must expand all variables manually, as in these lines:


    However, because each cron command is executed by a shell, a command can refer to variable names. For example, if you place this command:

    @daily  $HOME/bin/

    in your personal crontab (notice that the user name parameter is omitted in the line above), $HOME is expanded properly.

  • Do not schedule compute-intensive tasks to begin at the same time, such as @midnight. If possible, start such tasks independently throughout the wee hours of the morning, avoiding competition for resources.
  • As mentioned above, the environment variable SHELL is set to /bin/sh by default. If left unchanged, all commands in the crontab are interpreted by /bin/sh. However, if you aren't familiar with /bin/sh and prefer another shell, you can set SHELL and use your shell's syntax for commands.

    For example, if you set SHELL=/bin/zsh, all commands can use the facilities of the Z shell, such as its advanced redirection operators:

    @daily  uptime > daily >> weekly

    Here, the output of the command uptime overwrites the file named daily (>daily) and is appended to the file weekly (>> weekly).

  • Use the access control lists (ACLs)—/etc/cron.allow and /etc/cron.deny—to permit or preclude individual users from running cron jobs. If you want to greatly limit access to cron to just a few users, list those users' names in /etc/cron.allow. Anyone not named cannot submit a crontab using the crontab utility. However, if you want to grant wide access and prohibit just a handful of users from access to cron, list the restricted users in /etc/cron.deny.

    For example, if /etc/cron.allow looks like this:


    any user other than Joe and Zelda is refused access to cron:

    % whoami
    % crontab ~/.crontab
    You (strike) are not allowed to use this program (crontab)
    See crontab(1) for more information
  • To disable email reports from cron, put MAILTO="" in the crontab.
  • Again, do not use spaces in lists. Separate list values with commas. In Vixie cron, do not use day names and month names in ranges.
  • Read the documentation for your system's cron carefully. Paths can differ, as can features and conveniences. To read about crontab file syntax, type man 5 crontab at the command line. To read about the crontab utility, type man 1 crontab. To find the options available for the cron daemon itself, type man cron or man 8 cron at the command line.

The systems administrator's best friend

Cron and its ilk are invaluable for systems administration. If you find yourself performing the same task over and over again, consider automation with cron. Shell scripts are often necessary to capture complex tasks with many steps, but you can also achieve a great deal with a single command line run every so often.

Here are just a handful of ideas:

  • Combine cron and your favorite database tools to create daily dumps. For example, the command
    @daily joe mysqldump -pjoespwd accounts > $HOME/backups/accounts.`date +%F`.sql

    dumps the database named accounts daily to a file. The embedded date command (`date +%F`) ensures that the file name is unique, as in accounts.2008-08-07.sql. The command runs as joe, so Joe's password is specified with -p. This command could also simply appear in Joe's own crontab, because his MySQL credentials are required for the dump.

  • The locate subsystem indexes all files on the system and stores the full path to each file in a database. You can then query the database from the command line to instantly find files. Of course, you can search for files on demand with find, but you must wait as it crawls the file system each time it runs.

    To make locate effective, though, you must index the file system on a regular basis, because files come and go all the time. This is a perfect application for cron.

    0 0,12 * * * root updatedb

    This crontab entry runs updatedb, the locate update utility, twice per day.

  • Another obvious task well suited to automation with cron is copying files from a master to its many slaves. Rsync is a modern utility that distributes and synchronizes collections of files across multiple systems. Many Web masters combine cron and rsync to push a master copy of the Web site to each server in the farm.
    @midnight www rsync -avz /var/www/site slave1:/var/www

    At midnight each night, rsync exactly copies (-avz) /var/www/site to /var/www on slave1.

    Use the command-line mail utility and the shell pipe operator (|) to send the output of a task to one or more people on your staff.

    @weekly root df --print-type --local -h |& mail -s "Weekly df report" andy bob

    Here, the output of df is mailed weekly to users Andy and Bob to monitor disk usage.


Tutorial conclusion

Whether you run your own UNIX system or a system for hundreds of users, automating maintenance tasks saves time, reduces errors, and keeps machines humming through all hours of the night. Cron is a pivotal part of automation on UNIX systems, and with a little imagination, you can make your computer work for you instead of against you.

Cron can help you work smarter, not harder. Now, won't you sleep better?

Downloadable resources

Related topics

  • Learn more about the history of cron.
  • To discover the specifics of your cron subsystem, type man cron and man 5 crontab in any shell window.
  • Read more about anacron.
  • Check out additional UNIX tips and tricks from the developerWorks site.


Sign in or register to add and subscribe to comments.

Zone=AIX and UNIX
ArticleTitle=Using cron to automate maintenance