Author: Josh AmataLast Updated: Fri, Oct 15, 2021
This guide explains how to use Cron and Anacron to schedule tasks.
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:
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.
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:
Note: you should define these variables at the top of the crontab file, like:
SHELL=/bin/bash MAILTOemail@example.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.
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:
|0 3,9,12 ** <command>||Run command every day by 3am, 9am and 12pm|
|0 16 12 <command>||Run command hourly on the 16th day of the 12th month (December)|
|15 0-6 * 0 <command>||Run command 15 minutes past every hour between midnight and 6am, on every Sunday|
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:
To list all the cron jobs running on your system without opening crontab configuration files, simply enter the command:
$ crontab -l
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 -
willmark from creating cron jobs, simply:
Add the following lines:
Now save and close the file.
You have successfully denied both users -
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.
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.
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
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:
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
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:
In this guide, you have learned about the cron scheduler and how it works, how to schedule cron jobs, and scheduling anacron jobs.