Scheduling tasks using crontab in Linux

5/5 - (1 vote)
2,059 views

bash

Overview

Cron is a Linux/UNIX service that allows users to run scripts or programs automatically at a specified time and is commonly used to automate system maintenance or administration. It starts when the system boots and runs in the background as long as the system is up. The cron daemon is similar to the Task Scheduler application from Windows. It’s often useful to have a script or command executed without any human intervention. For example, you might want to have a script that creates regular backups of your files and folders and stores them in a specified location. For this cron is the perfect tool to do the job.

What is crontab

Crontab is a configuration file for the cron daemon and it a simple ASCII text file. Crontab files are split into two categories: user crontab files and system crontab files. Individual users can have their own crontab files which are stored under the /var/spool/cron/crontabs folder in most Linux distributions. These files are named after each user’s login name. For example if we had a user called cioby then we would have a file named “cioby” in the /var/spool/cron/crontabs folder.

The cron daemon looks for the system crontab files /etc/crontab and files in the directory /etc/cron.d. The format for these system crontabs differs slightly from user crontabs. System crontabs have an additional field for a username between the time specifications and the command.

In the /etc directory you might also find some sub directories called ‘cron.hourly‘, ‘cron.daily‘, ‘cron.weekly‘ and ‘cron.monthly‘. If a script is put in one of these directories as their name suggests it will be ran once an hour, daily, weekly or monthly depending on the directory name.

In order to create a new crontab file or edit an existing one you must use the crontab command with the ‘-e‘ switch.

# crontab -e

This command will invoke a text editor specified in the EDITOR or VISUAL environment variables. In order to change the default editor you must set the value of these variables to different editor.

export EDITOR=vi
export VISUAL=vi

You can change the vi editor with the one that suit your needs (e.g. pico or nano). Assuming our default editor is vi, invoking the crontab -e command will open either a blank file or and existing one which will allow us to add new entries. To add a new entry type ‘i‘ to enter insert mode and add the crontab line then save the file by pressing Esc key to exit insert mode and type :wq sequence followed by Enter key.

Crontab environment

In a crontab file we can set several environment variables which are used by the cron daemon. Below is an example from a crontab file:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

These variables are set up at the beginning of the file before any crontab lines. They have the following meanings:

  • SHELL – indicates the shell under which the cron daemon runs. Here it is /bin/bash. If it’s not specified it will default to the value from the /etc/passwd file.
  • PATH – specifies the directories in which cron will search to execute the command. If the command you run in a crontab line in not part of any directories specified in this variable you need to type the full path to the command or else it will fail to run. Another solution would be to add that directory to the PATH variable separated by a semicolon ‘;’
  • MAILTO – indicates where to send the output of the command. If this variable is not set the output will be mailed to the owner of the crontab. If MAILTO is defined but empty (MAILTO=””), no mail will be sent.
  • HOME – defines the home directory that is used for cron. If it’s not specified it will use the value defined in the /etc/passwd file.

Crontab file format

Each user crontab file contains seven fields:

minute hour dom month weekday user command

The first five fields tell cron when to run the command and the sixth field specifies the user which will run the command. They’re separated by whitespace, but within the command field, whitespace is passed along to the shell. To add comments in a crontab file we must begin each line with a ‘#‘ character. The meaning of each field is explained below:

  • minute – specifies the minute of an hour when to run a command and its range is between 0 – 59
  • hour – specifies the hour at which to run a command. It uses 24 hour format (0 – 23) and 0 indicates midnight
  • dom – represents the day of the month when to run a command and its range is between 1 – 31
  • month – specifies the month when the command will run. It can be specified using numerals (1 – 12) or month names (Jan – Dec)
  • weekday – specifies the day of the week when to run a command. It can be specified using numerals (0 – 7) or weekday names (Sun – Sat). Sunday is the first day and can be specified as 0 or 7.
  • user – specifies the user who runs the command
  • command – specifies the command to run. It can contain multiple words or spaces.

If a field contains an ‘*‘ character it means that it will match any possible value for that field. Cron supports also range of values separated by a dash ‘‘ or commas ‘,‘. For example if we want to run a command at 10 AM from Monday through Friday we would write a line like this:

* 10 * * 1-5 script.sh

Comma-separated list can be used to run a command at different hours in the same day. For example to run a command at 10,13,17 and 22 hours we would write:

* 10,13,17,22 * * * script.sh

Step values are also allowed by cron. They separate values by a ‘/‘ character. To run a command every 3 hours we would write:

* */3 * * * script.sh

Step values can be used in conjunction with ranges.

* 11,13,17-20 * * * script.sh

The above line will tell cron to run the command at 11 then at 13 and at last at every hour between 17 and 20.

Cron can use several special predefined values to substitute the 5 time fields, each value being prefixed by a ‘@‘ character. Below is the complete list.

  • @reboot – run once at system startup
  • @hourly – run once an hour => “0 * * * *”
  • @daily – run once a day => “0 0 * * *”
  • @weekly – run once a week => “0 0 * * 0”
  • @monthly – run once a month => “0 0 1 * *”
  • @yearly or @annually – run once a year => “0 0 1 1 *”

Crontab options

The crontab command which is used to install or edit a crontab file supports several options:

  • -e – this option allows to edit or create a crontab file using the editor specified in the EDITOR or VISUAL environment variables.
  • -l – displays the content of the current user crontab file on the screen.
  • -u – specifies the username whose crontab is to be tweaked. If the option is missing then crontab asssumes the user currently running the command.
  • -r – removes the crontab file for the current user.
  • -i – is similar to the ‘-r’ options but instead it prompts before removal.

If we ran the command:

$ crontab filename

it will install filename as your crontab, replacing any previous version.

Crontrolling access to cron

The capability to use crontab can be restricted by the system administrator by specifying who can use it and who cannot. Two config files, cron.deny and cron.allow allows us to controls these restrictions. They are located under the /etc directory in most Linux distributions. If the allow file exists, then it contains a list of all users that may submit crontabs, one per line. If the allow file does not exist but the deny file does, only those users not listed in the deny file may use the service. If neither file exists, all users have access to cron. As an example, if the allow file exists but does not contain john, then this user sees the following message when trying to run crontab while logged in:

$ crontab -e
You (john) are not allowed to use this program (crontab)
See crontab(1) for more information

To simply add users to these files you can edit them using any text editor or using echo command from the bash prompt to append names to the end of this files.

# echo john >> /etc/cron.allow

Changing cron output

By default the cron daemon is configured to send its output to the username or the mail address specified in the MAILTO environment variable. We can change this behaviour for example by redirecting its output to a local log file. To collect the cron execution to a log we need to add the ‘>‘ or ‘>>‘ characters after the command followed by the path to the log file.

@daily script.sh >> /var/log/script.log

In the above example the ‘>>‘ characters will append output to the end of the log file while using ‘>‘ will overwrite existing output. If you do not wish that the cron’s output to be mailed to you append the following at the end of the cronjob line.

@daily script.sh > /dev/null 2>&1

The above line will discard the output of cron.

Practical examples

Running a script every day at 12:00 PM

0 12 * * * /home/{username}/script.sh >/dev/null 2>&1

Running a script every day at 12:00, 14:00, 16:00

0 12,14,16 * * * /home/{username}/script.sh >/dev/null 2>&1

Running a script every Sunday at 13:30

30 13 * * 0 /home/{username}/script.sh >/dev/null 2>&1

Running a script on the 1st the 15th and the 20th day of each month

0 0 1,15,20 * * /home/{username}/script.sh >/dev/null 2>&1

Running a script every three hours 00:00, 03:00, 06:00 etc.

0 */3 * * * /home/{username}/script.sh >/dev/null 2>&1

Running multiple commands at 04:45 AM

45 4 * * * /usr/sbin/chkrootkit && /usr/bin/updatedb

Troubleshooting cron issues

By default cron will run at system startup. To check the if cron is running type the following command at bash prompt:

# ps -ef | grep cron

In some cases your username might be restricted to run cron jobs. In this case check if your user is listed in the /etc/cron.deny file. Other useful places to troubleshoot cron issues is to check the log files usually /var/log/syslog or /var/log/cron.

Leave a Reply

Your email address will not be published.