Scheduling

Revision / Modified: Jan. 02, 2002
Author: Tom Berger

Original documents:
http://www.mandrakeuser.org/docs/admin/acron.html
http://www.mandrakeuser.org/docs/admin/acron2.html
http://www.mandrakeuser.org/docs/admin/acron3.html

What Scheduling Can Do

You are sitting at your new Linux machine, happily typing away (or grudgingly trying to solve some weird problem ;)), when all of a sudden your hard disk spins up and your system shows all signs of some lively activity going on. After a few minutes, the activity trails off and everything is as it was. You have just encountered your first scheduled 'job'. Job is Unix slang for a program running in the 'background', i.e. without requiring user intervention.

Mandrake Linux comes with several preconfigured schedules which take care of system maintenance: updating the data bank for the 'locate' command, moving the logging files in '/var/log' ('rotating' them), running security checks, removing unused modules from system memory etc. If you are curious, have a look at the directories '/etc/cron.d/' (minute scheduled jobs), '/etc/cron.hourly/' (hourly scheduled jobs), '/etc/cron.daily/' and '/etc/cron.monthly/' which contain the scripts executed by the (ana)cron daemon via '/etc/crontab'.

Of course you can also take advantage of this system, e.g. for

In short: everything you have to or want to do regularly or at a certain time on your computer and which requires no interaction, you can let your system do for you.

'sleep', 'at', 'cron' and 'anacron'

These four are responsible for delayed and scheduled command execution:

'sleep' is already installed, since it is often used in shell scripts. The 'at' package isn't installed by default. 'cron' and 'anacron' are included in a standard installation, although 'anacron' might not be started at boot time by default.
Use the Mandrake Control Center (System - Services) to check and configure this service, or go the short way via the command line (as 'root'):

# chkconfig --list anacron

to check and

# chkconfig anacron on

to enable the service. (More on system services)

Note that 'anacron' isn't meant as a replacement for 'cron', it's an add-on.

'sleep'

Unless you are writing your own scripts (or are editing existing ones), 'sleep' won't be of much use for you. In scripts, however, it plays a quite prominent role. Its syntax is

sleep number of seconds

If you've ever watched the boot messages on an Mandrake Linux system closely, you will have noted the message

Press 'I' to enter interactive startup.

Have you ever managed to press the 'I' key fast enough? Well, I didn't. So I opened the file '/etc/rc.d/rc.sysinit' as 'root' in an editor. I found

if [ "$PROMPT" != "no" ]; then
 gprintf "\t\tPress 'I' to enter interactive startup."
 echo -en "\r"
 echo
 sleep 1
fi

which says that you have one second (sleep 1) to press the 'I' key. I changed it to sleep 5, so now Mandrake Linux leaves me five seconds to find the 'I' key and press it.

'sleep' is also used in a number of scripts which start a lot of programs to reduce disk usage by adding a pause between the commands.

Example: Pop-up Reminder

You have ten minutes left before you have to leave your computer. You want your box to tell you when these ten minutes are over.
This either requires 'xmessage' (part of the 'X11R6-contrib' package) or 'gmessage' (part of the 'gtkdialogs' package).

Enter this command into a virtual terminal (or the pop up command line of your window manager):

(sleep 10m; xmessage Time to leave!) &

This will pop up a message box on your desktop in ten minutes.

'at'

'at' adds scheduled jobs to the persistent 'at queue', managed by 'atd', the 'at daemon'. 'atd' must run for 'at' to work properly. You can check that as 'root' with

# service atd status

You can provide 'at' with absolute times, like 'April 30, 12.00' (at 1200 Apr 30), or with relative times like 'Tomorrow, 2.00 PM' (at 2pm tomorrow) or even 'In 5 hours, 25 minutes from now' (e.g. if it's 4 o'clock in the afternoon: at 0425pm + 5 hours). Valid time options are listed in '/usr/share/doc/at-[...]/timespec'.

Adding a job to the 'at queue' follows a somewhat peculiar scheme. You type in the time and - optionally - date first, hit <ENTER> and then add the command(s) to be executed (one per line). If you're finished, press <CTRL-d> on an empty line.

at [time] [date]<ENTER>
at>command 1<ENTER>
at>command 2<ENTER>
at> <CTRL-d>

warning: commands will be executed using /bin/sh
job number at full time and date

If the scheduled commands produce any output, 'at' will mail it to you.
To get a list of your queued 'at' jobs, run atq, to remove a job from the queue, use atrm job number.

Example: Sending yourself a scheduled reminder message

You have to make an important phone call in three days from now on at 4 pm. In order to be reminded of that, tell 'at' to send you a message half an hour before (your mail daemon must be configured properly for this to work):

at 0330pm today + 3 days
at> echo "remember call at 4!" | mail your username@localhost
at> <CTRL-d>

Notice the 'today' token. Strictly speaking it isn't necessary, but it makes sure that 'at' starts counting from today, regardless of the current time. If you would leave it out and it were past 3.30 pm already, 'at' would start counting from tomorrow at 3.30 pm and you would receive your reminder one day too late.

Administrativa

The 'batch' tool is part of the 'at' package. 'at' jobs invoked by 'batch' are only executed when the system load is below 0.8 (this value can be adjusted with the

atd -l value

command).
The default configuration allows all users to use 'at'. To exclude users, add their login names to '/etc/at.deny' (or add all privileged users to '/etc/at.allow').

Strictly speaking, there's no program called 'cron'. There is the 'cron daemon', crond, which is started automatically at boot, and the command 'crontab' to set up files to control 'crond', the 'crontabs'. Both 'Linuxconf' and 'Webmin' offer modules to configure 'cron' via a graphical interface.
The crontab system on Mandrake Linux is twofold: system wide crontabs are controlled by '/etc/crontab' and '/usr/bin/run-parts', which call scripts stored in '/etc/cron. d' (executed every minute), '/etc/cron.hourly', '/etc/cron.weekly' and '/etc/ cron.monthly'.
Crontabs for users (and 'root') however are stored in '/var/spool/cron/user_name'.

Specifying Execution Time

Have a look at '/etc/crontab', because it will tell you something about the 'crond' syntax. By default, the lower part of this file looks like this:

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

Each line starts with five fields denoting when the command (runparts directory) is to be executed:

  1. The first field denotes the minute,
  2. the second the hour,
  3. the third the day of month,
  4. the fourth the month (by number or short name)
  5. the fifth the day of the week (by number or short name)

An * (asterisk) marks an unrestricted field. This tells 'crond', "never mind what minute / hour / day / month / weekday it is, do it". Have a look at the last line. There you see: The command is executed at the 42th minute of the 4th hour (am) of the first day of a month. It doesn't matter which month (* in the fourth field) or which weekday (* in the fifth field).

A line like this:

* * * * * command

would execute command every minute, regardless of which hour / day / month it is. This should also explain how the first * in '/etc/crontab' works: 'execute the command in the first minute of every hour, on every day, in every month'.

* * * * mon command

would execute command every minute, but only on Mondays.

What does this?

44 14 * 11 wed command

Got it? It executes command on 2:44 pm every Wednesday in November.

Note that field three (day of month) and field five (day of week) are handled a bit differently, if they both list restrictions.
Assume you would change the last line of '/etc/crontab' to

42 4 1 * sun command

One might be inclined to think that this would restrict the execution of command to 4:42 am on the first day of every month, if that day happens to be a Sunday. However, if field three and field five both list restrictions, command is executed, when either field matches. So in this case on every first day of a month and on every Sunday.

You can also specify (multiple) ranges (x-y), lists (x,y,z) and step values (in conjunction with ranges, x-y/z):

05-15,30-40/3 8,12,16 * */2 7 command

Tough one, eh? ;-) Here's a hint: When you are trying to decipher more complicated 'crond' rules, read the fields from right to left:
The command is executed on Sundays (7), every second month (*/2, i.e. January, March, May etc), during the hours 8, 12 and 4pm. It is executed every minute between the fifth and fifteenth minute and every three minutes between the thirtieth and fortieth minute.
So in January 2003 the command would be executed at the 5th, 12th, 19th and 26th of January (Sunday), at every minute between 8:05am and 8:15am, and then at 8:30, 8:33, 8:36 and 8:39. Then at 12:05, 12:06, 12:07 etc.

Writing Your Own Crontab

To edit / create your crontab, issue

$ crontab -e

which opens a new file (or your existing crontab) in an editor.

Note that 'crontab' uses the (unjustly) infamous 'vi' editor by default. To make 'crontab' use your favorite editor, e.g. 'gedit', run this command before calling 'crontab':

$ export EDITOR=/usr/bin/gedit

There are also several graphical crontab editors available. KDE users may prefer KCron to the orphaned 'kcrontab', others Tct to the license-encumbered 'VCron' or the unstable 'GCrontab'.

The other options to 'crontab' are:

Commands that take two or more lines are not allowed. Put them into a script and call the script from the crontab instead.

If you want to execute commands which need the permissions of another user, e.g. 'root', use su to login into that account and run 'crontab' like this:

# crontab -e -u root

If the commands run via 'crond' produce any output or if errors occur, a mail is sent to the owner of the crontab the command was started from, provided a mail daemon like 'Postfix' is installed and running. This might be inconvenient for 'root' cron jobs, if you are your own administrator and don't get 'root's' mail. This behavior can be changed with the MAILTO variable in your crontab. It defines who should get mail for which job(s), or that no one should get mail for a job at at all:

MAILTO=""
job1br /> MAILTO=jim
job2

For job1, no mail will be sent (even if the job fails), the mail concerning the second job will go to user 'jim'.

Example: Monthly Compression Of 'sent_mail' Folder

You want cron to compress your 'sent_mail' file or folder, store it somewhere else and then empty the file or folder. Create a script like this:


#!/bin/bash
#
tar czf $HOME/mail/sent_mail$(date +%b%Y).tar.gz /path to/sent_mail_folder_or_file
# for mail file (mbox format) use this:
if $?=0; then
        echo > /path_to/sent_mail_file
else
        exit 1
fi
# for mail folder (mh format) use this:
if $?=0; then
        rm -f /path_to/sent_mail_folder/*
else
        exit 1
fi

(The 'if' construction prevents the cleaning of the sent_mail folder/file if tar has failed to create an archive.)

Make the script executable with chmod +x file. Next edit your crontab with crontab -e and put these lines in it:

# the next line catches all months with 31 days
59 23 31 1-7/2,8-12/2 * sh your_script_with_full_path
# the next line all months with 30 days
59 23 30 4,6,9,11 * sh your_script_with_full_path
# well, and February. Will be one day off in leap years
59 23 28 2 * sh your_script_with_full_path

If everything goes well, cron will call the script on the last minute of each month. The script will compress the 'sent_mail' folder/file, store it under '$HOME/mail/sent_mailMonthYear.tar.gz' and then empty the 'sent_mail' folder/file.

anacron

If you look at '/etc/crontab', the control file for the cron scheduling daemon, you will notice that by default all daily, weekly and monthly system tasks are run between 4 and 5 o'clock in the morning. If your computer isn't turned on during this time, the cron jobs won't be executed.
One solution to this problem would be changing the hour fields to a time when your system is most likely running (I used to change them to 2 pm.).
Another solution would be running the 'anacron' daemon.

'anacron', the 'anachronistic command scheduler', uses relative time scales ('once a day / week / month') instead of absolute time scales ('4:15am, Feb 15'). So, even if you 'miss' a particular time or date for which a job is scheduled, it will be executed shortly after you've booted the system. It works like this:

  1. 'anacron' looks up the 'timestamps' for its jobs in '/var/spool/anacron'.
  2. If according to a time stamp a job is due, 'anacron' will run it.
  3. 'anacron' updates the time stamp for the job.

'anacron' is controlled by the file '/etc/anacrontab'. If you open it in a pager, you will see that the preconfigured Mandrake Linux cron jobs are already entered in there:


1 5 cron.daily run-parts /etc/cron.daily
7 10 cron.weekly run-parts /etc/cron.weekly
30 15 cron.monthly run-parts /etc/cron.monthly
  1. The first field denotes the period in days: 1 is daily, 7 every 7 days (weekly) etc.
  2. The second field denotes the delay for jobs to be executed after anacron has started in minutes. So, 5 says 'run scheduled jobs 5 minutes after start'. This mechanism prevents queued jobs from being run all at the same time.
  3. The third field contains an identifier. 'anacron' uses this identifier for its timestamps and in messages.
  4. The fourth field finally lists the command to execute.

Caveats And Limitations

'anacron' is just an add-on to 'cron', not a replacement. Due to its very nature, it can't execute minutely or hourly scheduled jobs. It doesn't provide a mechanism for running jobs under different users, i.e. all jobs are run as 'root'.

Example: Getting Your New Mail After Boot

You want your computer to get your new mail after having booted it in the morning. Since you boot your machine at different times, a cron job won't do.
You need a properly configured mail daemon, a mail retrieving utility like Fetchmail and a scripted dial-up connection.

Add this command (one line) to '/etc/anacrontab':

1 3 getmail pppd call ISP && fetchmail -s && killall pppd

Since 'anacron' executes all commands as 'root', the '.fetchmailrc' file must have the permissions -rw------- root root set and should ideally reside in 'root's' home directory. Another possibility would be putting the commands into a script and putting su user before the line which starts 'fetchmail'.

Interactive Schedulers

'at', 'cron' and 'anacron' do not allow to start programs which require user input, like X applications. This is because they don't have a shell to start a program from. 'sleep' can do that, but only within a session.

Surprisingly enough there seems to be only one program currently which saves schedules to a file and thus allows to launch arbitrary interactive programs at a given time. This program is called 'rclock' and is part of the 'rxvt' package. If you find others, you are invited to tell me ;).


Legal: This text is covered by the GNU Free Documentation License. Standard disclaimers of warranty apply. Copyright LSTB (Tom Berger) and Mandrakesoft 1999-2002.