How to Use the Cron Task Scheduler

Updated on November 21, 2023
How to Use the Cron Task Scheduler header image

Introduction

This guide explains how to use Cron and Anacron to schedule tasks.

Prerequisites

  • A system running Linux such as CentOS, Ubuntu or Debian.
  • A user account with root or sudo privileges.

What is Cron?

The cron command-line utility is a built-in job scheduler on Unix-like operating systems such as Linux, used for running processes such as commands, scripts, etc at a scheduled time. Tasks such as system maintenance, backup automation, or more repetitive ones like downloading files and emails, running web scrapers, etc can be scheduled to run using cron.

The background service responsible for providing this cron functionality is the crond daemon. Cron’s actions are defined by crontab files, which are special configuration files that specify what shell commands to run periodically on a given schedule.

The cron service searches for crontab files in the following directories:

  • /var/spool/cron/crontabs - the files contained in this directory should not be accessed directly, instead use the crontab command to access and update them.
  • /etc/cron.d - system services and applications generally add cron job (crontab) files to this directory.
  • /etc/crontab - must be owned by the root user and must not be group- or other-writable.

Cron wakes each minute and examines all stored crontabs, inspecting each command to see if it should be run in the current minute. It also checks each minute to see if its spooldirectory’s modtime has changed, and if it has, cron will then examine the modtime on all crontabs and reload those that have changed, which negates the need to restart the cron service whenever a crontab file is modified.

Each user can have their crontab file.

Anatomy of a Crontab file

Cron uses a special format to read lines from crontab configuration files before executing the command.

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *  <command to execute>

Each line in this format represents a cron job:

30  17  7  *  *  /home/user/myscript/do_something.sh

Adding that line to a crontab file schedules a script do_something.sh to run by 17:30 (i.e 5:30p.m) on the 7th day of every month, anyday.
Each field should be separated by a space.

Note: the asterisk (*) is a wildcard character that signifies every possible value allowed. You could also specify a range of values by separating with a dash, or several distinct values by separating by a comma.

You can set up a default environment using the following variables:

  • SHELL - specifies what shell to use.
  • MAILTO - sets the email address where the cron job results will be sent.
  • PATH - sets a path for the environment.

Note: you should define these variables at the top of the crontab file, like:

SHELL=/bin/bash
MAILTO=test@test.com
PATH=/bin:/sbin:/usr/bin:/usr/sbin

These variables should be set specific to a given user because cron does not provide an environment of any kind.

Adding a Cron Job

To add a cron job, you must edit the crontab configuration file for the current user. To do this, enter the command in a terminal window:

$ crontab -e

Or to edit the crontab for a different user, enter the command (with sudo/root privileges):

# crontab -u user_name -e

A text file like the following will be opened for you to edit:

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow  command

Simply add your cron job in the format described earlier to the file:

30 17 7 * *  /home/user/myscript/do_something.sh

Now save, and close your editor. You have successfully added a cron job for the specified user.
Cron jobs added this way, will by default be saved under /var/spool/cron/crontabs.

By default, cron will send a mail to the specified mail address of the crontab owner after a cron job is one, to suppress this output email - add the string >/dev/null 2>&1 after the command field, like:

*  *  *  *  *  <command/script-to-execute> >/dev/null 2>&1

More examples of cron jobs:

Run command every day by 3am, 9am and 12pm:

0    3,9,12    **     *    <command>

Run command hourly on the 16th day of the 12th month (December):

0   *   16  12  *   <command>

Run command 15 minutes past every hour between midnight and 6am, on every Sunday:

15  0-6 *   *   0   <command>

Cron also allows the following special strings as shortcuts:

  • @reboot - run once, at startup.
  • @yearly - run once a year, same as 0 0 1 1 *”.
  • @annually - same as @yearly.
  • @monthly - run once a month, i.e 0 0 1 * *”.
  • @weekly - run once a week, i.e 0 0 * * 0”.
  • @daily - run once a day, i.e 0 0 * * *”.
  • @midnight - same as @daily.
  • @hourly - run once an hour, i.e 0 * * * *”.

For example, to run a command daily, simply use:

@daily  <command-to-execute>

Listing Cron Jobs

To list all the cron jobs running on your system without opening crontab configuration files, simply enter the command:

$ crontab -l

Restricting Cron Access

As a sysadmin, you might want to restrict regular users from creating cron jobs, due to possible misuse. To achieve this, you can limit user access by creating a /etc/cron.d/cron.allow file that contains the list of users separated by newlines with permission to create cron jobs.
Or alternatively, create a /etc/cron.d/cron.deny file containing a list of users to deny permission to create cron jobs (also separate users with newlines).

To restrict the users -janedoe and willmark from creating cron jobs, simply:

  1. Create the file /etc/cron.d/cron.deny if it doesn’t already exist and open it.

  2. Add the following lines:

     janedoe
     willmark
  3. Now save and close the file.

You have successfully denied both users - janedoe and willmark permission to create cron jobs.

Note: the root user cannot be denied permission to use cron this way.

As the root user, perhaps you denied another user permission to use cron, but also want to run a cron job for the denied user, simply use sudo/su to login in as root and access your crontab with crontab -e, then use this format to schedule a job for the other user:

*  *  *  *  *  <user>  <command/script-to-execute>

Alternatively, you can also run cron jobs for other users using this format as root.

Introducing Anacron

In the event of a system shutdown or sleep mode which causes cron to miss its scheduled jobs, those jobs will be skipped over as cron assumes the system is running continuously. This may not be optimal behavior, as you could miss out on important jobs such as data or email backups.

Anacron provides similar functionality as cron but has the ability to run jobs that were skipped over. The next time the system is turned on and completely booted, anacron checks to see if previously configured jobs missed their last scheduled run. If they did, anacron runs those jobs immediately, but only once regardless of how many cycles were missed. For instance, if a job was scheduled to run every day but hasn’t run for several days due to system shutdown, anacron will run the job once - when the system is booted notwithstanding how many days were missed.

Anacron reads a list of jobs from a special configuration file /etc/anacrontab, which contains the list of jobs that anacron controls. Each job entry specifies a period in days, a delay in minutes, a unique job identifier, and a shell command:

#period  delay  job-identifier  shell-command

The period specifies if the job has been run in the last n days, the delay specifies how long anacron should wait before running the job’s shell command, while the job identifier is a distinctive name for the job when writing to log files.

After the command executes and exits, the date is recorded in a special timestamp file for that job, so anacron can know when to execute it again - the hour is not used for time calculations, only the date.

Adding Jobs To Anacron

Unlike cron which is built-in, anacron must be installed. For ubuntu and debian systems, simply run the following command as sudo/root to install:

# apt-get update && apt-get install anacron

To add jobs to anacron, open the configuration file /etc/anacrontab, it should look like this:

# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root

#Start of job entries
#These replace cron’s entries
1   5     cron.daily      run-parts   --report    /etc/cron.daily
7   10   cron.weekly   run-parts   --report    /etc/cron.weekly
@monthly   15   cron.monthly   run-parts  --report    /etc/cron.monthly

Add entries in this format:

# period-in-days   delay-in-minutes   job-dentifier   shell-command

Example:

30    15    data-backup1    /bin/bash /home/user/myscripts/data-backup.sh

This will run our data-backup.sh script as soon as possible if it hasn’t been run in 30 days(a month) with a delay of 15 minutes before execution. This job will be identified by data-backup1 in log files.

Anacron isn’t designed to run scripts at specific times, rather it runs scripts at intervals beginning at specific times. You can fix time intervals by defining a special variable START_HOURS_RANGE before the job entries:

START_HOURS_RANGE=4-23

This will cause anacron to do jobs only between the hours 4-23 (4 a.m-11 p.m).

Another special variable is RANDOM_DELAY, which sets the maximum random delay added to the user-specified delay of a job (by default it’s 15).

Anacron supports shortcuts as we saw in cron earlier to specify the period. The previous entry could be written as:

@monthly   15    data-backup1    /bin/bash  /home/user/myscripts/data-backup.sh

Automated Options

Anacron also provides some simplified options to run regularly scheduled tasks. You can simply install your scripts in the following directories depending on your need, and anacron will handle the rest:

  • /etc/cron.hourly - scripts here run once each hour.
  • /etc/cron.daily - once daily.
  • /etc/cron.weekly - once per week.
  • /etc/cron.monthly - once per month.

Conclusion

In this guide, you have learned about the cron scheduler and how it works, how to schedule cron jobs, and scheduling anacron jobs.

Further Reading

Check out the man pages for cron, crontab and anacron to see more.