Command scheduling with cron
Posted by Steve on Mon 13 Dec 2004 at 19:25
Many pieces of system administration can be automated via perl scripts, or shell scripts which run at regular intervals. For example you might have a script to check that your disk isn't full which runs once an hour - informing you if there are problems. The most common mechanism for scheduling commands on Unix systems is via the cron package. This allows users to schedule arbitary commands to run at arbitary times with regular frequency.
In Debian the cron package is installed as part of the base system, and will be running by default.
Cron, as supplied in Debian, has two purposes:
- To run system jobs on a daily/weekly/monthly basis
- To allow users to setup their own schedules
The system schedules are setup when the package is installed, via the creation of some special directories:
/etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.monthly /etc/cron.weekly
Except for the first one which is special, these directories allow scheduling of system-wide jobs in a coarse manner. Any script which is executable and placed inside them will run at the frequency which its name suggests.
For example if you place a script inside /etc/cron.daily it will be executed once per day, every day.
The time that the scripts run in those system-wide directories is not something that an administration typically changes, but the times can be adjusted by editing the file /etc/crontab. The format of this file will be explained shortly.
The normal manner which people use cron is via the crontab command. This allows you to view or edit your crontab file, which is a per-user file containing entries describing commands to execute and the time(s) to execute them.
To display your file you run the following command:
root can view any users crontab file by adding "-u username", for example:
crontab -u skx -l # List skx's crontab file.
The format of these files is fairly simple to understand. Each line is a collection of six fields separated by spaces.
The fields are:
- The number of minutes after the hour (0 to 59)
- The hour in military time (24 hour) format (0 to 23)
- The day of the month (1 to 31)
- The month (1 to 12)
- The day of the week(0 or 7 is Sun, or use name)
- The command to run
More graphically they would look like this:
* * * * * Command to be executed - - - - - | | | | | | | | | +----- Day of week (0-7) | | | +------- Month (1 - 12) | | +--------- Day of month (1 - 31) | +----------- Hour (0 - 23) +------------- Min (0 - 59)
(Each of the first five fields contains only numbers, however they can be left as '*' characters to signify any value is acceptible).
Now that we've seen the structure we should try to ru na couple of examples.
To edit your crontabe file run:
This will launch your default editor upon your crontab file (creating it if necessary). When you save the file and quit your editor it will be installed into the system unless it is found to contain errors.
If you wish to change the editor used to edit the file set the EDITOR environmental variable like this:
export EDITOR=/usr/bin/emacs crontab -e
Now enter the following:
0 * * * * /bin/ls
When you've saved the file and quit your editor you will see a message such as:
crontab: installing new crontab
You can verify that the file contains what you expect with :
Here we've told the cron system to execute the command "/bin/ls" every time the minute equals 0, ie. We're running the command on the hour, every hour.
Any output of the command you run will be sent to you by email, if you wish to stop this then you should cause it to be redirected, as follows:
0 * * * * /bin/ls >/dev/null 2&>1
This causes all output to be redirected to /dev/null - meaning you won't see it.
Now we'll finish with some more examples:
# Run the `something` command every hour on the hour 0 * * * * /sbin/something # Run the `nightly` command at ten minutes past midnight every day 10 0 * * * /bin/nightly # Run the `monday` command every monday at 2 AM 0 2 * * 1 /usr/local/bin/monday
One last tip: If you want to run something very regularly you can use an alternate syntax: Instead of using only single numbers you can use ranges or sets.
A range of numbers indicates that every item in that range will be matched, if you use the following line you'll run a command at 1AM, 2AM, 3AM, and 4AM:
# Use a range of hours matching 1, 2, 3 and 4AM * 1-4 * * * /bin/some-hourly
A set is similar, consisting of a collection of numbers seperated by commas, each item in the list will be matched. The previous example would look like this using sets:
# Use a set of hours matching 1, 2, 3 and 4AM * 1,2,3,4 * * * /bin/some-hourly