Cron Jobs

Cron jobs allow you to repeatedly run commands. They can be run both in a timed manner, but also on bootup. While cron may seem a bit confusing in the beginning, it’s actually very simple to use once you know how it works.

Basic usage

To configure your cron jobs (the commands you want to run) in your so-called crontab, run crontab -e. The -e switch means edit. You will be presented with the editor currently set in your EDITOR environment variable. In most scenarios that will be vi(m) or nano.

If you have no experience with command line editors nano might be easier to use. If you want to make sure that it is used start with the following command.

export EDITOR=$(which nano)

For the duration of your shell session, nano will be your editor. Now run crontab -e

crontab -e

Depending on the system you are using, there might already be a default cron configuration file for your user. It usually only contains lines which are commented out, rendering them inactive. Since the crontab is mostly a shell script a # character will indicate the start of a single-line comment.

We will assume that your crontab is empty. If it isn’t, you can simply add the following examples at the beginning or end of your crontab.

Configuring Cron itself

Before we actually create our first cron job, it is good to know that there are some configuration variables to be aware of. None of these need to be set, as their defaults are usually sane and will be taken from your system. They are however useful to know about when debugging cron jobs.

  • SHELL: This will tell cron to use a certain shell. Changing this is barely ever required. The default is whatever /etc/passwd says for the current user.
  • MAILTO: The output of any command run by cron will be mailed to this address. It can contain either a full email address or an existing user on your system. By default this is set to the owner of the crontab (the user entering crontab -e).
  • CRON_TZ: This is used to set the time zones used for the command. UTC would be such a timezone. It defaults to your system’s time zone.

A basic cron tab

It might be useful to setup a basic cron file that only contains comments. This makes sure you don’t need to look up the manual page or this blog, when you just quickly need to change something. I also included some example cron jobs .

# Instead of the shell from /etc/passwd, always use /bin/sh to run commands

# SHELL=/bin/sh # mail any output to <email>, instead of the current user. This can also be a username.
# MAILTO=<email> # Set the time zone to UTC
# CRON_TZ=UTC

# Example Cron Jobs #

# Run at every boot up
# @reboot /usr/bin/dmesg # Mails dmesg output to current user 

# <minute> <hour> <day of month> <month> <day of week> <command>
# 0 0 * * * echo "run at midnight, every day"
# * 9-17 * * 1-5 echo "run every minute during usual business hours"
# */5 * * * * echo "run every five minutes"
# 0 0 1 1,3 * echo "it is January first or March first"

Let’s examine this example. The first block contains the configuration mentioned above. None of these settings are active as they are all prefixed with #. To activate them simply remove the #-sign in front of the individual variables.

The second block contains four commented (inactive) cron jobs. Since both dmesg and the shell’s echo command produce output, an email will be sent to the current user. Keep in mind that unless you’ve set up an e-mail server, this means that your user will receive local emails. These emails can be checked using the mail command, pico, pine and other mail clients that support local email. Another way is just looking into your user’s mail file. Per default this file is located in /var/spool/mail/<username> on most systems. However this may vary.

A cron job is defined by a time to run, followed by a command to run. Cron jobs are usually a single line, but like in shell scripts you can use a backslash (\) to do multi line cron jobs. For simplicity you should however try to stick to single line comments and write shell scripts, that are run via cron, if you need more complexity.

Nicknamed times

The first cron job we define uses @reboot. This mean that the command (/usr/bin/dmesg) is being run once after each boot (so after starting up the system, regardless of a whether you shut it down and turn it on again or are actually rebooting it). Many cron implementations support this instead of the classical commands. Other frequently supported nicknamed times involve things like @hourly or @daily to have commands being run on an hourly or daily basis. For more information on support for these use man 5 crontab to display your system’s manual page.

Cron time format

Next up, our crontab contains more classical cron entries. These are supported most implementation of cron. Here are the definitions:

  • * means “every”. It is a catch all. It can mean every minute, every hour, every day of the month,  every month and every day of the week
  • <number> Any kind of number. A number X that means that the command should be run on the Xth. In case of a month it’s the Xth month, so a 4 means April and a 0 in the minute means that a command is run at a full hour (minute 0). Using 0 as the hour means midnight, while 23 means 11PM (12 + 11). Here a list of allowed values:
    • Minute: 0-59
    • Hour: 0-23 (0 is midnight)
    • Month: 1-12
    • Day of week 0-7 (0 and 7 are Sunday)
  • <number>,<number> Lists allow you to specify multiple  entries, so for example 1,3 for a day would mean Monday and Wednesday. You can specify more than two. 1,15,20 in a day of month would mean that that something should happen every 1st, 14th and 20th of a month. One can also combine ranges this way.
  • <number>-<number> These are ranges. 1-3 would be equivalent to 1,2,3.
  • */<number> Every X. It allows you to specify a command to be run every X of a unit. For example */5 for the minute means that a command should be run every five minutes. One can also use ranges so 0-30/5 in minutes would mean every five minutes in the first 30 minutes of an hour.
  • <names> Instead of numbers months and days of the week can also be specified using names. They are three-letter abbreviations, for example sun for Sunday and apr for April.

Viewing the current crontab

To just print out (list) your current crontab you can use the -l switch.

crontab -l

Changing another user’s crontab

When you are root and you can view or edit another user’s crontab using the -u command to specify the respective user.

# Edit
crontab -u <user> -e

# View
crontab -u <user> -l

/etc/crontab and friends

Next to the user’s crontabs there also is a system crontab. It resides in /etc/crontab. It is meant to be used as a way to define a system wide crontab and is often used by configuration management tools and others. It often contains a default configuration that runs files or directories on a daily, weekly and monthly basis. On the BSDs these are usually called “periodics”. These are for pure convenience and allow software packages to come with their own cron jobs.

FAQ & Caveats

What happens when the computer is turned off?

If your system is not running then cron will not start the command. It will also not run any commands that it missed after bootup. There is no queue or similar way to store commands for the ‘next available moment.’ For most servers this isn’t a big problem, but for home servers or desktop systems it might be.

How to disable emails?

To completely disable email sending you can use MAILTO=””. This will also disable error messages. So instead you may want to pipe into a log file or to /dev/null, if you just want to disable it for single lines. See also the next question.

How to still receive error messages?

If you want to disable output but still be able to receive stderr messages (such as “file not found”) you may want to just pipe stdout to /dev/null. For example running cat somefile > /dev/null in your command line will result in no output, if the file exists, however you will still receive the “No such file or directory” message should the file be missing.

Commands run at the wrong hour

This either means that your system’s time is wrong or that the wrong timezone is set in your cron file. See the CRON_TZ variable above.

Command not found or File not found

When running cron without full paths or shell scripts without a full path you might run into the problem that cron runs inside a very limited environment. Either replace your commands and file paths with full paths (to find a full path use which <command>) or set the PATH environment variable.

Day of month caveat

Please keep in mind that not all months have the same amount of days. So if you use the 29, 30 or 31 as your day of a month your cron job won’t run every month. A similar thing applies to time zones which have daylight saving time, where cron jobs might not run or run twice.

 

Cron Basics Video

Dave created a video that covers the absolute basics of cron a while back. Check it out to make sure you’ve understood the concepts here:

 


Have fun!

1 reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *