Linux® and UNIX® systems allow you to schedule jobs in the future, either just once, or on a recurring schedule. This article, excerpted from the developerWorks tutorial LPI exam 102 prep: Administrative tasks, shows you how to schedule jobs periodically, and how to run a job at some future time.
Many administrative tasks must be done frequently and regularly
on a Linux system. These include rotating log files so filesystems do not become
full, backing up data, and connecting to a time server to keep your system time
synchronized. See the full tutorial mentioned above for more about these
administrative tasks.
In this tip, you learn about the scheduling facilities available in Linux using
the cron
and anacron
facilities and the crontab
and
at
commands. Even if your system sleeps or is turned
off, anacron
can help it catch up the next
time it is awake.
Running jobs at regular intervals is managed by the cron facility, which
consists of the crond
daemon and a set of tables
describing what work is to be done and with what frequency. The daemon wakes up
every minute and checks the crontabs to determine what needs to be done. Users
manage crontabs using the crontab
command. The
crond
daemon is usually started by the init process at
system startup.
To keep things simple, let's suppose that you want to run the command shown in
Listing 1 on a regular basis. This command doesn't actually do anything except
report the day and the time, but it illustrates how to use
crontab
to set up cron jobs, and we'll know when it was
run from the output. Setting up crontab entries requires a string with escaped
shell metacharacters, so it is best done with simple commands and parameters. In
this example, the echo
command will be run from within
a script /home/ian/mycrontab.sh, which takes no parameters.
This saves some
careful work with escape characters.
Listing 1. A simple command example
[ian@lyrebird ~]$ cat mycrontest.sh #!/bin/bash echo "It is now $(date +%T) on $(date +%A)" [ian@lyrebird ~]$ ./mycrontest.sh It is now 18:37:42 on Friday |
To create a crontab, you use the crontab
command with
the -e
(for "edit") option. This opens the
vi
editor unless you have specified another editor in
the EDITOR or VISUAL environment variable.
Each crontab entry contains six fields:
- Minute
- Hour
- Day of the month
- Month of the year
- Day of the week
- String to be executed by
sh
Minutes and hours range from 0-59 and 0-23, respectively, while day of month
and month of year range from 1-31 and
1-12, respectively. Day of week ranges from 0-6, with 0 being Sunday. Day of week
may also be specified as sun, mon, tue, and so on. The sixth field is everything
after the fifth field, and is interpreted as a string to pass to
sh
. A percent sign (%) is translated to a newline,
so if you want a % or any other special character, precede it with a backslash
(\). The line up to the first % is passed to the shell, while any line(s) after
the % are passed as standard input.
The various time-related fields can specify an individual value, a range of values, such as 0-10 or sun-wed, or a comma-separated list of individual values and ranges. A somewhat artificial crontab entry for our example command might look like the example in Listing 2.
Listing 2. A simple crontab example
0,20,40 22-23 * 7 fri-sat /home/ian/mycrontest.sh |
In this example, our command is executed at the 0th, 20th, and 40th minutes (every 20 minutes), for the hours between 10 P.M. and midnight on Fridays and Saturdays during July. See the man page for crontab(5) for details on additional ways to specify times.
You may be wondering what happens to any output from the command. Most commands designed for use with the cron facility will log output using the syslog facility that is discussed in the tutorial LPI exam 102 prep: Administrative tasks. However, any output that is directed to stdout will be mailed to the user. Listing 3 shows the output you might receive from our example command.
Listing 3. Mailed cron output
From ian@lyrebird.raleigh.ibm.com Fri Jul 6 23:00:02 2007 Date: Fri, 6 Jul 2007 23:00:01 -0400 From: root@lyrebird.raleigh.ibm.com (Cron Daemon) To: ian@lyrebird.raleigh.ibm.com Subject: Cron <ian@lyrebird> /home/ian/mycrontest.sh Content-Type: text/plain; charset=UTF-8 Auto-Submitted: auto-generated X-Cron-Env: <SHELL=/bin/sh> X-Cron-Env: <HOME=/home/ian> X-Cron-Env: <PATH=/usr/bin:/bin> X-Cron-Env: <LOGNAME=ian> X-Cron-Env: <USER=ian> It is now 23:00:01 on Friday |
The crontab that you created with the crontab
command
is stored in /etc/spool/cron under the name of the user who created it. So the
above crontab is stored in /etc/spool/cron/ian. Given this, you will not be
surprised to learn that the crontab
command, like the
passwd
command, is an suid program that runs with root
authority.
In addition to the user crontab files in /var/spool/cron,
cron
also checks /etc/crontab and files in the
/etc/cron.d directory. These system crontabs have one additional field between the
fifth time entry (day) and the command. This additional field specifies the user
for whom the command should be run, normally root. A /etc/crontab might look like
the example in Listing 4.
Listing 4. /etc/crontab
SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # run-parts 01 * * * * root run-parts /etc/cron.hourly 02 4 * * * root run-parts /etc/cron.daily 22 4 * * 0 root run-parts /etc/cron.weekly 42 4 1 * * root run-parts /etc/cron.monthly |
In this example, the real work is done by the
run-parts
command, which runs scripts from
/etc/cron.hourly, /etc/cron.daily, and so on; /etc/crontab simply controls the
timing of the recurring jobs. Note that the commands here all run as root. Note
also that the crontab can include shell variables assignments that will be set
before the commands are run.
The cron facility works well for systems that run continuously. For systems that may be turned off much of the time, such as laptops, another facility, the anacron (for "anachronistic cron") can handle scheduling of the jobs usually done daily, weekly, or monthly by the cron facility. Anacron does not handle hourly jobs.
Anacron keeps timestamp files in /var/spool/anacron to record when jobs are run. When anacron runs, it checks to see if the required number of days has passed since the job was last run and runs it if necessary. The table of jobs for anacron is stored in /etc/anacrontab, which has a slightly different format from /etc/crontab. As with /etc/crontab, /etc/anacrontab may contain environment settings. Each job has four fields:
- period
- delay
- job-identifier
- command
The period is a number of days, but may be specified as @monthly to ensure that a job runs only once per month, regardless of the number of days in the month. The delay is the number of minutes to wait after the job is due to run before actually starting it. You can use this to prevent a flood of jobs when a system first starts. The job identifier can contain any non-blank character except slashes (/).
Both /etc/crontab and /etc/anacrontab are updated by direct editing. You do not
use the crontab
command to update these files or files
in the /etc/cron.d directory.
Sometimes you may need to run a job just once, rather than regularly. For this
you use the at
command. The commands to be run are read
from a file specified with the -f
option, or from stdin
if -f
is not used. The -m
option sends mail to the user even if there is no stdout from the command. The
-v
option displays the time at which the job will
run before reading the job. The time is also displayed in the output.
Listing 5
shows an example of running the mycrontest.sh
script
that you used earlier. Listing 6 shows the output that is mailed back to the user
after the job runs. Notice that it is somewhat more compact than the corresponding
output from the cron job.
Listing 5. Using the at command
[ian@lyrebird ~]$ at -f mycrontest.sh -v 10:25 Sat Jul 7 10:25:00 2007 job 5 at Sat Jul 7 10:25:00 2007 |
Listing 6. Job output from at
From ian@lyrebird.raleigh.ibm.com Sat Jul 7 10:25:00 2007 Date: Sat, 7 Jul 2007 10:25:00 -0400 From: Ian Shields <ian@lyrebird.raleigh.ibm.com> Subject: Output from your job 5 To: ian@lyrebird.raleigh.ibm.com It is now 10:25:00 on Saturday |
Time specifications can be quite complex. Listing 7 shows a few examples. See the
man page for at
or the file /usr/share/doc/at/timespec
or a file such as /usr/share/doc/at-3.1.10/timespec, where 3.1.10 in this example
is the version of the at
package.
Listing 7. Time values with the at command
[ian@lyrebird ~]$ at -f mycrontest.sh 10pm tomorrow job 14 at Sun Jul 8 22:00:00 2007 [ian@lyrebird ~]$ at -f mycrontest.sh 2:00 tuesday job 15 at Tue Jul 10 02:00:00 2007 [ian@lyrebird ~]$ at -f mycrontest.sh 2:00 july 11 job 16 at Wed Jul 11 02:00:00 2007 [ian@lyrebird ~]$ at -f mycrontest.sh 2:00 next week job 17 at Sat Jul 14 02:00:00 2007 |
The at
command also has a
-q
option. Increasing the queue increases the
nice
value for the
job.
There is also a batch
command, which is similar to the
at
command except that jobs are run only when the
system load is low enough. See the man pages for more details on these features.
You can manage your cron and at jobs. Use the crontab
command with the -l
option to list your crontab, and
use the atq
command to display the jobs you have queued
using the at
command, as shown in Listing 8.
Listing 8. Displaying scheduled jobs
[ian@lyrebird ~]$ crontab -l 0,20,40 22-23 * 7 fri-sat /home/ian/mycrontest.sh [ian@lyrebird ~]$ atq 16 Wed Jul 11 02:00:00 2007 a ian 17 Sat Jul 14 02:00:00 2007 a ian 14 Sun Jul 8 22:00:00 2007 a ian 15 Tue Jul 10 02:00:00 2007 a ian |
If you want to review the actual command scheduled for execution by
at
, you can use the at
command with the -c
option and the job number. You will
notice that most of the environment that was active at the time the
at
command was issued is saved with the scheduled job.
Listing 9 shows part of the output for job 15 from Listings 7 and 8.
.
Listing 9. Using at -c with a job number
#!/bin/sh # atrun uid=500 gid=500 # mail ian 0 umask 2 HOSTNAME=lyrebird.raleigh.ibm.com; export HOSTNAME SHELL=/bin/bash; export SHELL HISTSIZE=1000; export HISTSIZE SSH_CLIENT=9.67.219.151\ 3210\ 22; export SSH_CLIENT SSH_TTY=/dev/pts/5; export SSH_TTY USER=ian; export USER ... HOME=/home/ian; export HOME LOGNAME=ian; export LOGNAME ... cd /home/ian || { echo 'Execution directory inaccessible' >&2 exit 1 } ${SHELL:-/bin/sh} << `(dd if=/dev/urandom count=200 bs=1 \ 2>/dev/null|LC_ALL=C tr -d -c '[:alnum:]')` #!/bin/bash echo "It is now $(date +%T) on $(date +%A)" |
Note that the contents of our script file have been copied in as a here-document that will be executed by the shell specified by the SHELL variable or /bin/sh if the SHELL variable is not set. See the tutorial LPI exam 101 prep, Topic 103: GNU and UNIX commands if you need to review here-documents.
You can delete all scheduled cron jobs using the cron
command with the -r
option as illustrated in Listing
10.
Listing 10. Displaying and deleting cron jobs
[ian@lyrebird ~]$ crontab -l 0,20,40 22-23 * 7 fri-sat /home/ian/mycrontest.sh [ian@lyrebird ~]$ crontab -r [ian@lyrebird ~]$ crontab -l no crontab for ian |
To delete system cron or anacron jobs, edit /etc/crontab, /etc/anacrontab, or edit or delete files in the /etc/cron.d directory.
You can delete one or more jobs that were scheduled with the
at
command by using the atrm
command with the job number. Multiple jobs should be separated by spaces. Listing
11 shows an example.
Listing 11. Displaying and removing jobs with atq and atrm
[ian@lyrebird ~]$ atq 16 Wed Jul 11 02:00:00 2007 a ian 17 Sat Jul 14 02:00:00 2007 a ian 14 Sun Jul 8 22:00:00 2007 a ian 15 Tue Jul 10 02:00:00 2007 a ian [ian@lyrebird ~]$ atrm 16 14 15 [ian@lyrebird ~]$ atq 17 Sat Jul 14 02:00:00 2007 a ian |
Configure user access to job scheduling
If the file /etc/cron.allow exists, any non-root user must be listed in it in
order to use crontab
and the cron facility. If
/etc/cron.allow does not exist, but /etc/cron.deny does exist, a non-root user who
is listed in it cannot use crontab
or the cron
facility. If neither of these files exists, only the super user will be allowed to
use this command. An empty /etc/cron.deny file allows all users to use the cron
facility and is the default.
The corresponding /etc/at.allow and /etc/at.deny files have similar effects for the at facility.
If you'd like to know more about administrative tasks in Linux, read the tutorial "LPI exam 102 prep: Administrative tasks," from which this article was excerpted, or see the other Resources below. Don't forget to rate this page.
Learn
- Review the tutorial
"LPI
exam 102 prep: Administrative
tasks"
(developerWorks, Jul 2007) for more information on other administrative tasks in
Linux, including user administration, backups, system logs, and Network Time
Protocol. It is part of a larger
LPI
exam prep tutorial series
covering Linux fundamentals and preparing you for system administrator
certification. Other tutorials from the series that are referenced in this article
are
LPI
exam 101 prep:
GNU and UNIX commands
and
LPI
exam 101 prep:
Devices, Linux filesystems, and the Filesystem Hierarchy Standard.
- The
Linux
Documentation Project has a
variety of useful documents, especially its HOWTOs.
- In the
developerWorks Linux zone,
find more resources for Linux developers, including
Linux tutorials,
as well as
our readers' favorite Linux articles and tutorials
over the last month.
- Stay current with
developerWorks technical events and Webcasts.
Get products and technologies
-
Order the SEK for Linux,
a two-DVD set containing the latest IBM trial software for Linux from DB2®,
Lotus®, Rational®, Tivoli®, and WebSphere®.
- With
IBM trial software,
available for download directly from developerWorks, build your next development
project on Linux.
Discuss
- Participate in the discussion forum.
- Get involved in the
developerWorks community
through our developer blogs, forums, podcasts, and community topics in our new
developerWorks spaces.

Ian Shields works on a multitude of Linux projects for the developerWorks Linux zone. He is a Senior Programmer at IBM at the Research Triangle Park, NC. He joined IBM in Canberra, Australia, as a Systems Engineer in 1973, and has since worked on communications systems and pervasive computing in Montreal, Canada, and RTP, NC. He has several patents and has published several papers. His undergraduate degree is in pure mathematics and philosophy from the Australian National University. He has an M.S. and Ph.D. in computer science from North Carolina State University. You can contact Ian at ishields@us.ibm.com.