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:
- cron expression: A string that describes the time or times when the command should be run
- user (optional): If the crontab is specified in a centralized location instead of the user's personal crontab file, this field contains the username that the command should be run as. This allows cron to run a command as you, even if you're not logged in at the time. This field isn't used in a user's personal crontab file.
- command: The rest of the line is interpreted as the command that cron should run at the specified time.
"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:
/etc/cron.d
,/etc/cron.daily
,/etc/cron.hourly
, and so on: System crontabs, or crontabs installed by a software package/var/spool/cron/<username>
: Users' crontabs; these are created and managed with thecrontab
command.
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 commandcopy-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.
* * * * *
: every minute0 * * * *
: every hour, on the hour0 0 * * *
: every day at midnight server time0 0 * * 0
: every Sunday at midnight server time*/10 * * * *
: every ten minutes0 */4 * * *
: every four hours, on the hour
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.
- If you want to run something every N hours, be sure to specify a minute expression (the first number) also; otherwise, the command will be run once a minute for the entire hour.
- Commands run by cron won't have all of the configuration and environment
variables that come from your shell initialization files (like
.bashrc
or.zshrc
or such). In particular, make sure to specify the full path to your program if it's not in a commonly-used location like/usr/bin
. - If you have problems with the syntax, or something isn't working properly, there are websites [2] that will translate crontab to English, and vice versa. [3]
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]
[1] | "Examples" in cron - Wikipedia, a free encyclopedia |
[2] | Crontab to plain English |
[3] | English to crontab |
[4] | Where can I set environment variables that crontab will use? |
[5] | Receive notifications when cron commands fail |