How to setup crontabs

crontab syntax

Users often ask what are the crontab arguments and how to set it up ... or copy from others who were made aware of the secret of the arcane and ancient Unix lore :-) ... No mystery to it though, here is a quick primer.

Structure

Listing, uploading entries

First, it is probably easier to create a file my.cron (or similar) containing your entries and then, use the command
 % crontab my.cron
to upload them. BUT however, this is NOT recommended if you are working in a multi-user environment as the above command would replace the cron entries of the current user by the content of the file my.cron .  BE SURE to then do this first
% crontab -l  >my.cron
which lists the existing entries and redirect to the file my.cron, edit and modify and reload.
Note that
% crontab -e
also invokes the editing of the cron entries ... BUT it assumes the EDITOR environment variable is set (if not set, a default editor will be used likely vi).

Fields and entry format

The structure of the enries in itself is as below - if I want to execute the famous "hello world" every minute and add it to a file, here is what I would do:


#.- 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 
#|  |  | | |  |
# My hello world example - does nothing else that growing a log

 *  *  * * *  echo "Hello world"         >>/home/jlauret/cron.log

Note that I indicated all fields and their meaning above. In this case the output is redirected to a log file /home/jlauret/cron.log.
Lines with "#" are comments. Take the habit to leave a line of explanation before each cron entry to tell what it does - this may help you (or others if you share the same management account or group account).

Tricks worth knowing about cron

While the crontab syntax is not very well documented in the manpages (a bit obscure especially in the Linux manpages), the manpages will provide you with much information on anything else. So, visit
% man crontab

Of interest, the Linux cron accepts variable=value at the head of a cron. For example, within the first lines of a crontab file, you may add something like
SHELL=/bin/sh
and this will make any commands executed later in the crontab entries as running under "sh" AND bypassing whatever you may have as shell set in your account. Another useful variable is MAILTO (if MAILTO does not work, try MAIL as there are slight differences depending on the version of the cron service).
MAILTO=jlauret@bnl.gov
will send any errors or non-redirected (to a log) output to jlauret@bnl.gov . Note that if you do NOT redirect output to a file, the default behavior is already to send the results to the local account. Be careful to remember that both STDOUT and STDERR have to be take care off. In my simple example above, only the standard output was redirected to /home/jlauret/cron.log. You may change this redirect to something like

*  *  * * *  echo "Hello world"         >>&/home/jlauret/cron.log

to make sure both standard out and errors are redirected to that log file.

A tiny trick is that

MAILTO=""

will stop cron from sending any Emails. This is NOT recommended as it may be your only hope to catch problems with your cron.

You could also use a redirect like >&/dev/null under csh ( or >/dev/null 2>&1 if your default shell is sh) to disable a specific cron entry output. If you append to a log (like in our example >>/home/jlauret/cron.log), consider removing up the log regularly. A "/bin/rm -f /home/jlauret/cron.log" once a month would do. Typically, you would remove the log before you execute a cron cycle again.
 

Range, repetition or steps

The following syntax are available under Linux (be careful that under old OS and version of cron, those may not be valid)
*  *  * * 1-5  echo "Hello world" 

to run from Monday to Friday. The dash "-" indicates a range of values in this case. Similarly, the slash "/" indicates a step or a repeat every N. For example:
 

*/2  *  * * *  echo "Hello world"

would mean repeat every two minutes while
 

0  0-23/2  * * *  echo "Hello world"

would mean do do it at midnight and every two hours after that (range and repeat are combined here, of course you may limit to hours of the night only). You may also specify a more standard syntax 9should work on ANY version of cron):

0  0,2,4,6,8,10,12  * * *  echo "Hello world"

to have the entry repeated from 0 (midnight) to 12 (noon) every two hours. Similarly, combination of ranges are possible under Linux i.e. you may specify fields like 0-6,20-23 (in our example, this would work for the hour field). Again, this would not work with ATT and BSD crons (older) so if you want to write standard cron entries, avoid too many fancy syntax while if you work under Linux mainly, would be a pity not to use their conveniences.
 

Other trick - the "@" syntax

Special keywords exists for cron and appears to be prefixed with the "@" sign. They are listed below

@reboot	  : Run once after reboot.
@yearly	  : Run once a year, i.e.  "0 0 1 1 *".
@annually : Run once a year, i.e.  "0 0 1 1 *".
@monthly  : Run once a month, i.e. "0 0 1 * *".
@weekly	  : Run once a week, i.e.  "0 0 * * 0".
@daily	  : Run once a day, i.e.   "0 0 * * *".
@hourly	  : Run once an hour, i.e. "0 * * * *".

The could appear like this in your cron entries
 

# perform miscellaneous management
@monthly  /home/jlauret/bin/monthly-maintenance

# wipe the C drive free space once a month
@monthly  /home/jlauret/bin/wipe -s c

# weekly remove garbage files left over by editors
@weekly /bin/rm -f /cygdrive/c/Users/jlauret/.saves-*

The entries are in this case of the form @tag CMD. Again, do not expect those to work with older version of cron. But you could use those tags under linux to perform special repeated tasks. The @reboot indicates to execute the command only once after the machine has rebooted (this may come handy to check that a service has started / restarted).
 

Notes and warnings

  • Remember that when a cron entry is executed, NO SHELL is fully executed (that is, your .cshrc or .bashrc are not sourced) hence you may not use a full login variable on the command line. Particularly, if you execute a script (perl or otherwise), note that your regular shell environmnet variables will not be available within your script. To circunvent this, you could wrap your perl (or otherwise) based advanced script by a simple csh wrapper - this would load your .cshrc then execute your perl script.
     
  • A HIGH risk of problems with cronjobs is that (a) your program execution gets stuck and (b) the next cron cycle starts another instance of it. Please, always make sure that when your script runs, it checks no other instances are actually running (kill previous instance and run or quite immediately). Otherwise, the machine load may go high and the node will eventually crash.
     
  • If you use unix commands directly in cron entries (like the above /bin/rm example) make sure as in the example that you use fully specified path and executable.
     
  • You can not use % in the command area. They will need to be escaped and if used with a command like the date command you can put it in backticks like in `/bin/date +\%Y-\%m-\%d`.
     
  • If your password have expired or similar, all crons will stop functioning.
    If you execute the below command and get the below message
    % crontab -l
    You (jeromel) are not allowed to use this program (crontab)
    See crontab(1) for more information
    
    this indicates that either you have no access (rights) to use cron or you had rights but your account has expired. You may also disabled via the /etc/cron.allow and /etc/cron.deny mechanism.

cygwin - how to set cron up

To setup cron under cygwin, you need a few steps ...

First, contab on cygwin are configured by
 % cron-config
and follow the instructions ... You need to do this only once (cron service will be set then once for all).

You can verify the service is running by typing
 % net start cron

The cron service is started by
 % cygrunsrv -I cron -p /usr/sbin/cron -a -D

but cron-config will do this for you so no need for the net start or the cygrunsrv command.

To verify the logs and see if your cron entries executed properly, use
 % cronevents
And that is all. cygwin crons may be used to actually manage your Windows computer very easily (delete garbage, run updatedb regularly and forget about Windows indexing service taking lots of CPU, ... ).