Laziness is considered a virtue in system administration, meaning you should figure out ways to avoid having to perform the same task regularly by hand. Cron to the rescue!
cron is the time-based job scheduler in Unix-like computer operating systems. cron enables users to schedule jobs (commands or shell scripts) to run periodically at certain times or dates. It is commonly used to automate system maintenance or administration, though its general-purpose nature means that it can be used for other purposes, such as connecting to the Internet and downloading email.
cron allows you to run routine jobs on a Unix-based system automatically at a specific future time or at regular intervals rather than running such jobs manually. Even knowing just the basics of cron is a huge win, as this tool increases productivity, saves time and is not prone to human error, i.e. forgetting to run a job.
“crontabs” (or cron tables) are the way that a user schedules a job to run under cron. They’re composed of the following parts:
“crontab” may also refer to a file containing any number of these cron tables, one per line.
crontab files are commonly found in a couple of different places:
The easiest way to see jobs running regularly on the system (aka “cron jobs”) is to type:
user@opsschool ~$ crontab -l
in the shell. This will show all the cron jobs scheduled to run as the current user. For example, if you are logged in as jdoe and there are no cron jobs running the output will be something like:
jdoe@opsschool ~$ crontab: no crontab for jdoe
If there are jobs scheduled to run, there will be a list of lines that looks something like this:
05 12 * * 0 /home/jdoe /home/jdoe/jobs/copy-to-partition
The way to schedule a new job is to type:
user@opsschool ~$ crontab -e
in the shell. This will open an editor with your personal “crontab” file (or an empty file if you don’t have any cron jobs already scheduled).
Then add a line to the file that looks like this:
0 * * * * date
and save and close the file.
The cron job you just created will run the command date at the top of every hour (e.g. at 10:00, 11:00, 12:00, etc.). Depending on how your system is configured, it may begin to email you the output of that command each time it’s run, or it may be saved to a log file somewhere.
Let’s look again at the example from before:
05 12 * * 0 /home/jdoe /home/jdoe/jobs/copy-to-partition
Let’s dissect this a bit, as it will help when you’re creating your own cron jobs. What is this output telling you? It is helpful to know what the fields of a “crontab” are. Here’s a table with the order of fields, and their values:
MINUTE HOUR DAYOFMONTH MONTH DAYOFWEEK COMMAND 0-59 0-23 1-31 1-12 0-6 filepath/command
Note
Order matters, and note that the first element is 0 for the minute, hour, and day of the week fields, while the day of the month and month fields begin at 1.
Knowing this, we can see that this “crontab” means:
At 12:05 every Sunday, every month, regardless of the day of the month, run the command copy-to-partition in the /home/jdoe/jobs directory.
Caveat: entries in your crontab must be one long line; if you try to split it up (with the linebreak \ character for example) you will get an error!
Let’s take another example and create a cron job that checks disk space available every minute, every hour, every day of the month, every month, for every day of the week, and outputs it to a file named :file:disk_space.txt.
* * * * * df -h > disk_space.txt
This would get us what we wanted (df -h is the unix command for checking free disk space).
Field values can also be ranges. Let’s say you want to edit this job to run the same command (df -h), but instead of running every minute, you only want the job to run it in the first 5 minutes of every hour, every day of the month, every month, for every day of the week.
Running crontab -e again and changing the line to:
0-5 * * * * df -h > disk_space.txt
will get you what you want.
Lastly, if you want to remove the command, again type crontab -e, and then delete the line with that job in it from the file in your editor.
To remove all cron jobs for the current user, type:
crontab -r
The “cron expression” syntax can be confusing to understand. Here are some common expressions to get you started.
Here is the standard “cron expression” cheat sheet [1]:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .----- day of week (0 - 7) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * command to be executed
Put this template at the top of your crontab file so it’ll be easy to remember what the fields do.
The crontab command can be used to view or modify a specific user’s crontab file, instead of the current user’s crontab file. For instance, if you are logged in as jdoe and you want to edit jsmith‘s crontab (and you have the permissions to do so), type the following in a shell:
jdoe@opsschool ~$ crontab -e -u jsmith
This option also combines with the other options we looked at before (-l for listing and -r for removing a user’s crontab file).
With some cron implementations [4], you can add shell environment variables to the top of a crontab file that affect all of the commands run by those crontabs. For example, you could modify the PATH, MAILTO, HOME, or any other variable.
Output from cron commands can be emailed to the owner of the process using a local SMTP server, like ssmtp or postfix. If you’d like the output to be sent to an email different than your root@yourhost address use the MAILTO="your@email" expression before the cron command. An email will be sent containing the output from STDOUT/STDERR every time the command executes. Unfortunately, the email gives no indication of the return status of the process (success or failure) and often leads to a cluttered inbox.
Note
If your crontab is misconfigured you won’t receive an email at all. Finding such failures (the lack of an email in your inbox) is hard to detect. To save time and avoid these silent failures, it is better to use a service that will notify you only on cron failures. [5]