Cron is a time-based job scheduler for Unix-like operating systems. It is used to automate various tasks, typically system maintenance and administration related jobs such as:
- Backing up databases, files, and directories.
- Creating and sending scheduled reports for certain activities or events.
- Verifying if a service is accessible.
Cron allows these tasks to be executed periodically at selected times, dates,
months, and intervals. The cron
command utility can be found on all Unix-like
systems, most commonly on macOS and Linux-based systems.
This article will explain the Cron syntax and show you how to create and edit cron jobs on a Linux-based machine. You'll also learn how to monitor cron jobs so that if a job fails to run, you will be notified so that you can take the appropriate action to fix the problem.
Prerequisites
Before continuing with the sections below, ensure that you have a Linux-based machine at hand. This could be a PC, virtual machine, virtual private server, or WSL (if you are using Windows). You also need root access so ensure to login to your machine using a non-root user with administrative privileges.
We'll be demonstrating the concepts discussed in this article on an Ubuntu 22.04 server, but the steps should be pretty similar on most mainstream Linux distributions.
Step 1 — Getting started with Cron
The cron
command utility comes preinstalled on every Ubuntu installation, so
you can check its status using the following command:
sudo systemctl status cron
● cron.service - Regular background program processing daemon
Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: >
Active: active (running) since Wed 2022-08-31 16:23:02 UTC; 4min 9s ago
Docs: man:cron(8)
Main PID: 751 (cron)
Tasks: 1 (limit: 2258)
Memory: 408.0K
CPU: 3ms
CGroup: /system.slice/cron.service
└─751 /usr/sbin/cron -f -P
If you're getting the same output above, it means cron
is up and running on
your system, and you can skip ahead to the next section. However, just in case
the service is not found or not installed on your machine, we will describe how
to install and set it up in this section.
First, update your system repositories to the latest version using the following command:
sudo apt update -y
After the updates are completed, you can install Cron on your system:
sudo apt install cron -y
Next, you'll need to enable the service and start it so that it is launched in the background and keeps running even if the server is rebooted:
sudo systemctl enable cron
Synchronizing state of cron.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable cron
sudo systemctl start cron
Check the status of cron
again:
sudo systemctl status cron
At this point, you should observe that the cron
service is now up and running.
Step 2 — Writing your first Cron job
In this section, we will discuss how to automate a simple but repetitive task
using Cron. All Cron jobs are managed through a special program called
crontab
, and every operating system user has their own crontab
file which is
located in the /var/spool/cron/crontabs/
directory.
You can open up your crontab
file using the following command:
crontab -e
If you are running this command for the first time, you will get the following output asking you to select a text editor:
no crontab for eric - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
Select /bin/nano
and press Enter
. Your default crontab editor will be set to
Nano and a temporary crontab
file will be created and opened in the editor.
This file contains some text explaining a Cron expression's basic syntax. Note
that any line beginning with the #
character is signifies a comment.
# Edit this file to introduce tasks to be run by cron.
. . .
# 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
Basic Cron syntax
A Cron expression has the following structure:
minute hour day_of_month month day_of_week command
Each of the above fields takes the following values:
minute
:0-59
hour
:0-23
day_of_month
:1-31
month
:1-12
orJAN-DEC
day_of_week
:0-6
orSUN-SAT
command
: Any operating system commands. When you need to execute multiple commands in one Cron Job, you can chain them together using&&
.
For example, the expression below means the commands
curl https://betterstack.com
and curl https://www.google.com
will be
executed every Sunday at 04:05 AM. The asterisk (*
) is a wildcard variable,
meaning that all possible values are accepted. Cron will treat the first five
parameters, separated by spaces, as scheduling parameters, and the rest will be
treated as Linux commands.
. . .
5 4 * * sun curl https://betterstack.com && curl https://www.google.com
Lastly, press CTRL + X
to exit the editor, and then press Y
to save the
file, and it will be saved as /var/spool/cron/crontabs/<username>
. You can
open this file again using the same command (crontab -e
). Note that
crontab -e
opens a file in the /tmp
directory instead of the actual crontab
file so that it can check your modifications for errors and prevent you from
overwriting your actual crontab file with those errors.
Let's now look at how to define more complex schedules with cron. For example, you might want the job to repeat every Monday, Tuesday, and Saturday at 00:00. To define schedules like this, we need a more powerful syntax, as shown in the list below:
*
: This is a wildcard variable representing "all". For instance,* * * * *
means this Cron Job will be repeated every minute of every hour of every day.,
: Commas are used to break up values to form a list. For instance,0 0 * * mon,tue,sat
specifies a job which repeats at 00:00 every Monday, Tuesday, and Saturday.-
: A hyphen is used to define a range of values. For example,0-9 * * * *
means this job will be repeated for the first 10 minutes of every hour of every day./
: A forward slash is used to define a step interval. For example,*/5 * * * *
defines a job that will be repeated every 5 minutes.
To make sure you are familiar with these syntaxes, here are some more examples:
5 7 3 8 *
: Every August 3rd at 7:05 AM.23 0-20/2 * * *
: At minute 23 for every second hour from 0 to 20. (00:23, 02:23, 04:23, and so on)0 0,12 1 */2 *
: At 00:00 and 12:00 for the first day of every second month. (February 1st, April 1st, June 1st ...)
If you're still having trouble understanding these expressions, there is a handy
website called Crontab guru that allows you to test a
Cron expression before using it in your crontab
. Besides these special
syntaxes, Cron also tries to simplify your workflow by introducing these
shortcuts.
@reboot
: the scheduled task will run once at system startup.@yearly
or@annually
: run once a year, same as0 0 1 1 *
.@monthly
: run once a month, same as0 0 1 * *
.@weekly
: run once a week, same as0 0 * * 0
.@daily
or@midnight
: run once a day, same as0 0 * * *
.@hourly
: Run once every hour, same as0 * * * *
.
You can replace the schedule variables using these shortcuts like this:
@yearly curl https://google.com
The above Cron expression is the same as:
0 0 1 1 * curl https://google.com
Step 3 — Managing crontab
files
Besides the crontab -e
command discussed earlier, which is used to open the
corresponding crontab
file for the current user, there are some other
available commands for crontab
:
crontab -l
: echos the current contents of thecrontab
file to the console.crontab -r
: Remove the currentcrontab
file. You should not use this command for safety reasons because it won't ask you to confirm the deletion of thecrontab
file.crontab -r -i
: This is the recommended command to use when you wish to delete acrontab
file, as it will ask you to confirm your choice like this:
crontab -r -i
crontab: really delete eric's crontab? (y/n)
crontab -e
: This command opens up yourcrontab
file for editing.sudo crontab -u <user> -e
: If a user has been granted root privileges, that user will be able to edit another user'scrontab
file using this command.
If you manage an operating system with multiple users, you may create prevent
certain users from accessing these crontab
commands for security reasons.
This can be done by specifying usernames in a /etc/cron.deny
file or a
/etc/cron.allow
file. The former prevents users in the file from accessing the
crontab commands while the latter allows only the users in the file to access
the commands. If both files are present, then cron.allow
will override
cron.deny
, meaning that a user present in both files will be granted access to
the crontab
command.
For instance, if you want to deny access to all users but grant access to only a specific user, you can use the following commands:
sudo echo ALL >>/etc/cron.deny # deny access to all users
sudo echo jack >>/etc/cron.allow # grant access to the user `jack`:
Step 4 — Executing script files with Cron
In this section, we'll automate a sequence of commands in order using a shell script. This script will retrieve system usage information such as CPU, memory and disk usage, as well as internet speed, and save them to a file.
Go ahead and create a new directory in your home directory with the following command:
cd ~ && mkdir scripts
Create a new script file within the scripts
directory, and populate it with
the following contents:
nano scripts/system-usage.sh
#! /bin/bash
: > ~/system-usage.txt
echo "============================== CPU and Memory Usage ==============================" >> ~/system-usage.txt
top -b -n 1 >> ~/system-usage.txt
echo "================================== Disk Usage ====================================" >> ~/system-usage.txt
df -h >> ~/system-usage.txt
echo "============================= Internet Speed Test ================================" >> ~/system-usage.txt
speedtest >> ~/system-usage.txt
Before running the script, ensure to install the speedtest-cli
package with
the following command:
sudo apt install speedtest-cli
Next, make the script executable by the current user:
chmod +x scripts/system-usage.sh
Test the script to confirm that it's working as expected:
./scripts/system-usage.sh
Once the script exits, check the contents of the system-usage.txt
file in the
home directory:
cat ~/system-usage.txt
You should observe the following output:
============================== CPU and Memory Usage ==============================
top - 18:18:28 up 1 day, 1:55, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 130 total, 1 running, 129 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 3.2 sy, 0.0 ni, 96.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1927.7 total, 1289.0 free, 152.1 used, 486.6 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1612.4 avail Mem
. . .
================================== Disk Usage ====================================
Filesystem Size Used Avail Use% Mounted on
tmpfs 193M 1.1M 192M 1% /run
/dev/sda1 38G 2.0G 34G 6% /
tmpfs 964M 0 964M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda15 253M 1.1M 252M 1% /boot/efi
tmpfs 193M 0 193M 0% /run/user/1000
============================= Internet Speed Test ================================
Retrieving speedtest.net configuration...
Testing from Hetzner Online GmbH (5.161.145.150)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by All Points Broadband (Ashburn, VA) [1774.19 km]: 1.337 ms
Testing download speed................................................................................
Download: 1328.87 Mbit/s
Testing upload speed......................................................................................................
Upload: 910.45 Mbit/s
Now, create a Cron job that runs this Bash script periodically.
crontab -e
Add the following line to the end of the file and quit your editor afterward:
*/5 * * * * bash ~/scripts/system-usage.sh
With this configuration in place, your system usage information will be
retrieved every 5 minutes, and the output will be saved to the
~/system-usage.txt
file as demonstrated earlier.
Step 5 — Monitoring Cron output
Since the Cron Jobs are executed in the background, you will not receive feedback when the task executes so you must actively monitor each Cron Job to get notified when it succeeds or fails. Typically, there are two major ways to monitor your cron jobs and both will be demonstrated in this section.
1. Monitoring cron jobs via email
By default, cron
will attempt to send an email if your scheduled task produces
some output such as the one shown below:
* * * * * <command> && echo "Cron Job executed."
However, for this to work, you need to set up an SMTP server on your machine. In
this section, we'll talk about how to send emails using
sSMTP and Gmail. Start by installing
ssmtp
on your computer:
sudo apt update
sudo apt install ssmtp
Next, open its configuration file:
sudo nano /etc/ssmtp/ssmtp.conf
Update the contents of the file as follows:
#
# Config file for sSMTP sendmail
#
# The person who gets all mail for userids < 1000
# Make this empty to disable rewriting.
root=<your_email_address>
# The place where the mail goes. The actual machine name is required no
# MX records are consulted. Commonly mailhosts are named mail.domain.com
mailhub=smtp.gmail.com:465
# Where will the mail seem to come from?
rewriteDomain=gmail.com
# The full hostname
hostname=<your_hostname>.<your_ip>.tld
# Use implicit TLS (port 465). When using port 587, change UseSTARTTLS=Yes
TLS_CA_FILE=/etc/ssl/certs/ca-certificates.crt
UseTLS=Yes
UseSTARTTLS=No
# Username/Password
AuthUser=<your_email_address>
AuthPass=<password>
AuthMethod=LOGIN
# Are users allowed to set their own From: address?
# YES - Allow the user to specify their own From: address
# NO - Use the system generated From: address
FromLineOverride=YES
One thing to note is that you must enable 2-Step-Verification for your Google
account and then generate a unique
App Password to use in
ssmtp.conf
, you cannot use your Google password directly.
Next, open your crontab file again, and this time, you can output the content of
the system-usage.txt
file:
crontab -e
. . .
MAILTO="<your_email_address>"
*/5 * * * * bash ~/scripts/system-usage.sh && echo "$(cat ~/system-usage.txt)"
Remember to add the MAILTO
option shown above, otherwise, the cron emails will
be sent to <username>@gmail.com
. This particular job will run every five
minutes, and the output will be sent to the email address specified by MAILTO
.
Wait for five minutes, and you should receive the following email in your inbox:
2. Monitoring Cron Jobs with a cloud service
Another way to monitor Cron Jobs is by use a cloud service that provides Cron monitoring capabilities. This is typically the way to go for serious production applications where the sustained failure of a scheduled task can potentially cause a massive problem for the business.
Better Uptime is a monitoring tool that offers Cron Job monitoring services. It provides much more flexibility for alerting options and keeps track of the health of the service over time. You can set up the exact person or team that should be alerted when a job fails and even create status pages for communicating downtime to your customers.
In this section, you will use Better Uptime to monitor the system usage cron job that you set up earlier. First, you need to create a free Better Uptime account if you don't have one already. Once signed in, click Heartbeats on the navigation menu and create your first heartbeat.
Enter an appropriate name for your monitor and how often you expect the monitored task to be repeated (five minutes in this case). Do enter an appropriate grace period to account for slight delays due to the network. In the On-call escalation section, select how you wish to be notified when an incident is detected. Once you are done, click the Save Changes button.
You will see this page next:
The highlighted URL above is what Better Uptime uses to monitor your Cron activity. You need to set up the job such that once it executes, a HEAD, GET, or POST request is made to this URL. Once Better Uptime receives the request, the job will be recorded as successfully executed.
Suppose the request is not received for any reason within the specified time period (including the grace period). An incident will be recorded and you will be notified through the appropriate channel.
Head back to the terminal and open your crontab
file once again:
crontab -e
Edit the cron job that you wish to monitor:
. . .
*/5 * * * * bash ~/scripts/system-usage.sh && echo "$(cat ~/system-usage.txt)" && curl https://betteruptime.com/api/v1/heartbeat/<your-heartbeat-monitor-id>
Save this crontab by exiting your editor, then wait for the job to run. You should observe that your monitor is marked as "Up" meaning that the job is running as scheduled.
You can also make a request to the Better Uptime URL in the bash script like this:
. . .
curl https://betteruptime.com/api/v1/heartbeat/<your-heartbeat-monitor-id>
This way, when you have multiple scripts in one job, you can set up a heartbeat for each script, and you'll be able to tell which one is not working when an incident happens.
If you want to simulate an incident, stop the cron
service with the command
below:
sudo systemctl stop cron
Better Uptime will stop receiving the requests and mark your monitor as "Down":
You will also get an alert in the configured channels:
You can view details about the incident or acknowledge it, indicating that you are working to resolve it, or you can escalate the incident further by alerting one or more members of the relevant team, or even the entire organization.
Final thoughts
In this tutorial, we discussed how to use the cron
utility to automate tasks
on Linux and how to monitor cron jobs through email or a cloud monitoring
service like Better Uptime.
You should now understand the Cron scheduling syntax and how to create and
monitor any cron jobs. To learn more about the cron
command, see its
manual page
(man cron
), or view checkout
these articles tackling
common questions about the program.
Make your mark
Join the writer's program
Are you a developer and love writing and sharing your knowledge with the world? Join our guest writing program and get paid for writing amazing technical guides. We'll get them to the right readers that will appreciate them.
Write for usBuild on top of Better Stack
Write a script, app or project on top of Better Stack and share it with the world. Make a public repository and share it with us at our email.
community@betterstack.comor submit a pull request and help us build better products for everyone.
See the full list of amazing projects on github