The Complete Guide to Linux Cron Jobs
If you’ve spent any time working on a
*nix-based operating system, chances are you’ve heard the term cron job, but for many developers cron jobs remain a source of confusion and painful mistakes.
In this article, you will learn more about the basics of cron, exploring the syntax for creating a cron job, as well as how to manage your cron jobs using the
crontab command. We’ll also review common mistakes that developers make when configuring cron jobs.
What Is a Cron Job?
Cron is a Linux program that allows users to schedule the execution of a piece of software, often in the form of a shell script or a compiled executable. Cron is typically used when you have a task that needs to be run on a fixed schedule, and/or to automate repetitive tasks like downloading files or sending emails.
At its most basic level, a cron job is an entry written into a table called the cron table, otherwise known as the crontab for short. This entry contains a schedule and a command to be executed. The cron daemon (crond) looks for entries in the crontab to determine what jobs it should run, and when it should run them according to the specified schedule.
Note: The examples below are run on the Ubuntu operating system. Different Linux OSs might use different package managers, but all other commands will work the same.
How Does Cron Work?
Most standard installations of cron consists of two commands:
crond, which is the daemon that runs the scheduling utility
crontab, which is the command that allows you to edit the cron entries for your jobs
When you talk about a daemon from a Linux perspective, it’s a program that is running in the background and is noninteractive. This means that the program does not accept any user input and doesn’t display output to the user. The word daemon is historically used in a Unix/Linux context and is not a universal term across different operating systems.
The daemon will be running under the root user. You can run the following command to see if cron is running:
$ ps aux | grep cron
You should see an output like this:
root 617 0.0 0.0 9420 2800 ? Ss 17:00 0:00 /usr/sbin/cron -f
If you received no output from the command at all, either cron isn’t running or is not installed.
On Ubuntu you can quickly install cron by running the following command:
$ sudo apt update && sudo apt install cron
If you’re using something other than Ubuntu, you’ll need to run the equivalent command for your package manager.
Once cron is installed, remember to make sure it is enabled and running using the
systemctl command provided by systemd:
$ sudo systemctl enable cron
Cron should now be running, and you should be able to see it if you again run the
ps command shown above.
Cron Schedule Syntax
A basic crontab entry looks something like this:
* * * * * /home/user/bin/somecommand.sh | | | | | | | | | | | Command or Script to execute | | | | | | | | | Day of week(0-6 | Sun-Sat) | | | | | | | Month(1-12) | | | | | Day of Month(1-31) | | | Hour(0-23) | Min(0-59)
An asterisk (*) matches all values, so if you take a look at the example above, it specifies that /home/user/bin/somecommand.sh should be run at minutes 0-59 and hours 0-23 on days of the month 1-31 for months 1-12 on days of week 0-6 — or in other words "every minute".
Cron entries can also be configured to run at more complex times. If you want to run four times a day between Monday and Friday, you can use the step operator ( / ) and the range operator ( - ).
0 */6 * * Mon-Fri /home/user/somejob.sh
That entry will run your command every six hours starting at midnight — 12:00 a.m., 6:00 a.m., 12:00 p.m., and 6:00 p.m. — but only from Monday to Friday.
If you want to delve deeper into other complex scheduling examples, crontab.guru is a handy website for testing out the scheduling syntax, and translating them into plain english.
Managing Crontab Entries
Once cron is running, it checks for crontab entries in the following files every minute:
- /var/spool/cron/crontabs/$USER (where
$USERis the currently logged-in user)
The first file, /etc/crontab, is a system-generated file containing shortcut commands designed to check for cron table entries in the following directories:
/etc/cron.monthly. There are a few other locations where cron jobs can be stored; to learn more about those, you can check out this post. For the purpose of this article, you will concentrate on creating new crontab entries for your user.
You can achieve this by using the
crontab command. From the terminal, enter edit mode for your user’s crontab using the following command:
$ crontab -e
The first time you run this command, the OS should ask you what editor you would like to use with a little menu like this:
no crontab for user - 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 :
Select the editor of your choice. If you’ve never used an editor on a Linux system before, go ahead and stick with the suggestion of using
nano, as it’s an easy-to-use editor for the most part.
Once you’ve made your selection, the editor you’ve chosen will come up with the default crontab for your user, like this:
Currently, the file is empty, but you are now free to add a cron job entry to the bottom of the file.
Common Errors & Mistakes
Up until now, you may have the impression that cron seems like quite a powerful tool and nothing can go wrong while using it. Right? Wrong.
Any experienced system administrator who has spent any amount of time setting up cron jobs will tell you that cron jobs will and do fail all the time, for a myriad of reasons.
Here’s an overview of some of the problems you could run into when setting up your cron jobs.
It’s not difficult to make a mistake with the cron syntax, especially if you haven’t worked with it before. Maybe you’ve swapped around the minutes and the hours part of the syntax. Again, you can always use the crontab.guru website to verify that your syntax is correct.
Another frequent occurrence is that your shell script works perfectly from the command line when you run it but it doesn’t seem to run from the cron entry. If your script invokes any environment variables, this is probably the cause. Cron does not load variables from files like .bashrc or bash_profile, so even if you’ve specified a common variable like
$USER, that variable isn’t defined when the cron daemon runs your job entry. You would either need to hard-code your variable values or manually load the values from files like .bashrc yourself.
Script Executable Permissions
By default, when you create a shell script, it does not have execute permissions:
$ touch shell_script.sh $ ls -als *sh
0 -rw-rw-r-- 1 user users 0 May 21 13:26 shell_script.sh
The file is missing execute permissions. Give the file executable rights by running the following command:
$ chmod +x shell_script.sh $ ls -als *sh
Now the output looks like this:
0 -rwxrwxr-x 1 user users 0 May 21 13:26 shell_script.sh
This should fix the missing execute permission that cron needs to be able to run the script.
Your script can be incredibly resilient, yet when system resources are depleted, no amount of resilience is going to help your cron job run successfully. Unfortunately, the only way to prevent this is to stay on top of monitoring your servers for metrics like available disk space, available memory, and sufficient open files.
You might have a cron entry that runs quite frequently and successfully within seconds. For argument’s sake, maybe you’re running that script every minute. It’s highly possible that an outside variable can interfere with the job completing on time, causing the job to take more than a minute to complete. The cron daemon will happily spawn more copies of your script until you have a small army of them all running at the same time, thus depleting system resources. You’ll need to build in checks like lock files to make sure only a single copy of your script is running at any given time.
Finally, external variables are beyond your control. If, for example, you have a script that pulls information from a REST API endpoint and something about the endpoint that you’re querying changes without notifying you, your cron job could be failing without your knowledge.
There are a few other ways that your jobs could fail, or cause confusion. We've put together answers to some of the most common questions below.
Where are cron jobs saved?
Learn about the five locations cron jobs can be saved.
Where are cron logs stored?
Learn where cron logs are stored on your operating system.
How to list all cron jobs?
Learn how to list all active cron jobs on a server.
No MTA installed, discarding output
Learn what causes this common cron error.
How to configure cron job env vars?
Learn about the various cron config variables.
What is the cron job working directory?
Learn how to list the working directory that cron uses when invoking your job.
How to fix bad minute crontab error?
Learn about this common cron configuration error.
How to fix crontab missing newline before EOF?
Learn about this common cron configuration error
Errors in crontab file, can't install
Learn what causes this output when saving a crontab file.