Archive

Crontab Format

Essential reading: man 5 crontab

The first and most important thing to remember about crontabs is that there are two types of crontab. There’s the system crontab, kept in /etc/crontab (and files in /etc/cron.d/, /etc/cron.daily/, /etc/cron.hourly/ and /etc/cron.weekly/). Then there’s the user crontabs, which are edited by running crontab -e and viewed with crontab -l. These have subtly different formats, and if you put the wrong format in the wrong place, things will not work (or at best, not as you expect them to).

System crontab format

Each line in the system crontab contains 7 whitespace-separated fields. These are, in order:

  • minute
  • hour
  • day of month
  • month
  • day of week
  • user
  • command

The user field indicates the user to run the command as. The command is taken to the end of the line.

User crontab format

Each line in a user crontab contains ony 6 whitespace-separated fields. These are:

  • minute
  • hour
  • day of month
  • month
  • day of week
  • command

Note that in a user crontab, there is no user field, and all commands are run as the user that owns the crontab. Also note that the root user’s user crontab is not the same as the system crontab in /etc/crontab.

How to write crontab time specifications

cron wakes up every minute, and checks the first five fields of each line in every crontab to see if they match the current time (to the nearest minute). If they do, the corresponding command is executed. A line is considered to match if either one of the “day” specifiers matches.

A * in a field matches all possible values of that time.

A number or list of numbers in a field matches only that number or set of numbers.

A */n (where n is a number) matches possible value of the field in steps of n.

So:

  • * * * * * runs the command every minute (since it always matches everything)

  • 5 * * * * runs the command at 5 past every hour

  • * 5 * * * runs the command every minute from 05:00 to 05:59 inclusive every day

  • 0 5 * * * runs the command once every day at 05:00

  • 0,12,24,36,48 * * * * runs the command five times every hour, at those minutes past

  • */12 * * * * runs the command every 12 minutes, starting on the hour (exactly the same as above)

  • */13 * * * * runs the command every 13 minutes, starting on the hour: at 0, 13, 26, 39 and 52 minutes past each hour. Note that the last gap is smaller than 13 minutes.

  • 5 9 * * 1 runs the command at 09:05 every Monday morning.

  • 5 9 13 * 5 runs the command at 09:05 every Friday morning and every 13th of the month

  • 5 9 1 */2 * runs the command at 09:05 on the first of every other month.

It’s worth bearing in mind, where you can avoid it, not to run cron jobs exactly on the hour — especially if you use ntpdate or some other means to automatically correct clock-drift. Often, such things interfere with cron, resulting in the specified job either running later than scheduled, or not at all.

You can’t make cron run only on the first Saturday of every month on its own. The time specification 5 9 1-7 * 6 will run on the first 7 days of the month and on every Saturday. The trick here is to use a wrapper script that checks for one or other of the conditions:

5 9 1-7 * * run-on-dow Sat echo “Wake up! It’s a [[HantsLUG]] meeting day!”

Where run-on-dow is something like:

if [[ `date|+%a` = $1 ]]; then     shift     exec "$@" fi

Leave a Reply