cron utility is used for running scripts and commands at regular intervals, and at specific times and dates. It’s built into most Linux distros, and provides a very useful way to schedule tasks on your server.
cron is an automation tool, so anything that you run on a regular basis can likely be switched over to a cron job. If you wanted to make regular daily backups, or restart a service once a week,
cron can do that.
How Does Cron Work?
Cron jobs are defined in a file called the crontab. This file is unique to each user, and while they’re usually located under
/var/spool/cron/crontabs, they’re not intended to be edited directly. Instead, you edit them through the
This will open your user’s crontab in your default CLI text editor. If this got you stuck in vim, you can change the default editor by running
select-editor on some systems, or by adding
export VISUAL=micro; to your
~/.bashrc (or shell equivalent).
By default, your crontab is likely blank, so you’ll have to add jobs manually. A cron job is usually formatted as:
minute hour day month weekday <command-to-execute>
The command to execute can be anything, including shell scripts
The values for each time variable can be wildcards, which cron will interpret as always true. For example, if you wanted to run a job fifteen minutes past every hour, every day, you’d use:
15 * * * * command
This will run on minute 15 of each hour, each day, each month, no matter the day of the week.
If you wanted to run a job at 5:30 PM on every Friday, you’d use:
30 17 * * 5 command
cron also supports ranged and stepped values. Ranged values include every value within a specific range. If you wanted to run a job every hour while you’re working, you’d use:
0 9-17 * * 1-5 command
From 9 AM to 5 PM, Monday through Friday. Similarly, you can define a list of values by separating them with commas.
Stepped values run at more specific intervals. You can run jobs every two hours using:
0 */2 * * * command
Keep in mind that the clock starts at midnight, 00:00. Your job will run once then, then at 2 AM, then at 4 AM and so on.
Some versions of
cron support more syntax, such as
@daily to run once a day, or
@reboot to run on every reboot, though your distro may vary.
If you want an easy way to debug
cron syntax, there are many online editors such as crontab.guru that will show you what your schedule expression means in layman terms, i.e. “At minute 0 past every 2nd hour.”
Making Sure Cron is Working
Cron doesn’t show you any indication that it’s running your jobs. If you’d like to know if it’s working, you’ll need to redirect the output manually. You can do this by piping the output to a log file:
* * * * * echo "test" >> logfile 2>&1
>> operator appends the output to a file, and the
2>&1 operator makes sure to include stderr in the output. The bash equivalent would just be
&>> in place of the
>>, but that may not work on every distro, since cron uses
/bin/sh by default.
Cron can be configured to send emails with the output of jobs. It actually does this by default with your user account’s default email address, but it likely isn’t configured properly. To get email working, you’ll need a mail agent set up and configured on your server, which will allow you to use the
Now, any output from any job that goes to stdout (e.g., it isn’t piped somewhere) will be sent through
* * * * * echo "cron mail is working!"
Just make sure to turn that job off once it is working, or it will get annoying very quickly.
Cron Uses /bin/sh By Default, Not Bash
You may be using a different shell than what
cron runs your jobs in. Bash (
/bin/bash) is a common shell on most distros, and is an implementation of sh. The
/bin/sh file is a symlink to an
sh implementation, but it isn’t always bash. On Debian based systems like Ubuntu, and on macOS,
/bin/sh links to
dash by default.
The end result of this confusion is that your scripts might not run the same, and your PATH variable (among others) may not be configured properly. You can get around this in a few ways, and your distro’s variant of
cron may work differently, so you may have to try a couple:
SHELL=/bin/bashto the top of your crontab. You may also have to add
BASH_ENV="/root/.bashrc"for it to read your bash profile.
/bin/bashbefore the command in each job. You may need to set the
BASH_ENVvariable even if you’re not switching to bash globally.
- Using the bash shebang
#!/bin/bashat the top of each script. This requires you to have each job in its own script file.
In any case, you should debug your cron jobs by setting them to run a few minutes ahead before considering them to be reliable.
Manually Updating Your Crontab
If you’d rather not manage your crontab through
crontab -e, there’s better method you can use. The command
crontab -l will display the contents of your crontab, and you can pipe this out to a file:
crontab -l > my_crontab
And then upload that file onto another system, and ‘install’ it with:
This way, you won’t cause any errors by editing it directly, as it’s still loaded in through