CRON User's Guide
Manual Revision 10-21-90
CRON Version 1.2
Shareware by
Tron Hvaring
PO Box 371
N-8501 Narvik
Norway
Phone: +47 82 44145
Fax: +47 82 44 160
BIXname: thvaring
CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring
CRON User's Guide Rev. 10-21-90 Contents
TABLE OF CONTENTS
1 INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Product Description . . . . . . . . . . . . . . . . . . . . 1
1.2 Shareware . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 2
1.4 System Requirements . . . . . . . . . . . . . . . . . . . . 2
1.5 Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2 INSTALLATION . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1 Archive Contents . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Installing CRON . . . . . . . . . . . . . . . . . . . . . . 3
2.3 Setting up CRON's environment . . . . . . . . . . . . . . . 3
2.4 Set Your Clock . . . . . . . . . . . . . . . . . . . . . . . 4
3 USING CRON . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1 Command-line Summary . . . . . . . . . . . . . . . . . . . . 5
3.2 Crontab override -- the '-c tab' option . . . . . . . . . . 5
3.3 Disable logging -- the '-n' option . . . . . . . . . . . . . 6
3.4 Swap Mode -- the '-s', '-d dir' and '-e' options . . . . . . 6
3.5 Verbose mode -- the '-v' option . . . . . . . . . . . . . . 6
3.6 Locking the logfile -- the '-L' option . . . . . . . . . . . 7
3.7 Stopping CRON . . . . . . . . . . . . . . . . . . . . . . . 7
3.8 Startup Information . . . . . . . . . . . . . . . . . . . . 7
4 THE CRONTAB IN DETAIL . . . . . . . . . . . . . . . . . . . . . 8
4.1 Syntax Summary . . . . . . . . . . . . . . . . . . . . . . . 8
4.2 The Date and Time fields . . . . . . . . . . . . . . . . . . 8
4.3 The Command Field . . . . . . . . . . . . . . . . . . . . . 9
5 THE CRONLOG IN DETAIL . . . . . . . . . . . . . . . . . . . . . 12
5.1 General Description . . . . . . . . . . . . . . . . . . . . 12
5.2 Starting And Stopping CRON . . . . . . . . . . . . . . . . . 12
5.3 Start and Stop of CRONTAB Entry Processing . . . . . . . . . 13
5.4 Logging Multi-Command Execution . . . . . . . . . . . . . . 14
6 ERROR HANDLING . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.1 General Considerations . . . . . . . . . . . . . . . . . . . 15
6.2 Failure to Spawn a Command . . . . . . . . . . . . . . . . . 16
6.3 A Spawned Command Fails . . . . . . . . . . . . . . . . . . 16
6.4 Other Internal CRON errors . . . . . . . . . . . . . . . . . 17
6.5 Exit Codes and COMMAND.COM . . . . . . . . . . . . . . . . . 17
7 ADVANCED TOPICS . . . . . . . . . . . . . . . . . . . . . . . . 18
7.1 Resource Requirements . . . . . . . . . . . . . . . . . . . 18
7.2 Using CRON with DESQview . . . . . . . . . . . . . . . . . . 18
7.3 CRON Technical Information . . . . . . . . . . . . . . . . . 19
7.4 Differences between CRON and UNIX cron . . . . . . . . . . . 19
8 REFERENCE SECTION . . . . . . . . . . . . . . . . . . . . . . . 21
8.1 Error Messages . . . . . . . . . . . . . . . . . . . . . . . 21
CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring
CRON User's Guide Rev. 10-21-90 Contents
8.2 Exit Codes . . . . . . . . . . . . . . . . . . . . . . . . . 22
8.2.1 Common Exit Codes . . . . . . . . . . . . . . . . . . 22
8.2.2 Swap Mode . . . . . . . . . . . . . . . . . . . . . . 23
8.2.3 Non-Swap Mode . . . . . . . . . . . . . . . . . . . . 23
8.2.4 RC = -1 for '!' Commands . . . . . . . . . . . . . . 23
9 UTILITY PROGRAMS . . . . . . . . . . . . . . . . . . . . . . . . 24
9.1 CDD.EXE . . . . . . . . . . . . . . . . . . . . . . . . . . 24
9.2 LOGCHECK.EXE . . . . . . . . . . . . . . . . . . . . . . . . 24
10 PROGRAM HISTORY . . . . . . . . . . . . . . . . . . . . . . . . 26
CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring
CRON User's Guide Rev. 10-21-90 Page 1
1 INTRODUCTION
1.1 Product Description
This is version 1.2 of CRON.
CRON is a timed command dispatcher that closely implements all the
features of the UNIX 'cron' utility that make sense in a DOS
environment.
CRON reads a special file at startup, conventionally called CRONTAB,
where each entry defines a time and a command to execute at that time.
All commands are periodic, i.e. one-shot commands are not possible. The
longest period is one year, however, so this is not considered a
problem. In a PC environment, a command with a 1-year period is a one-
shot command for all practical purposes.
After a command has executed, CRON re-calculates its next execution
time, then sorts the command list in time order and waits until the
first command in the list is due for execution. This sequence is
repeated undefinitely (or until the user stops CRON).
CRON optionally logs its activites in a file conventionally called
CRONLOG. The layout of this file is more or less identical to the UNIX
cronlog and conveys the same information. The cronlog maintains an
accurate track of CRON's activities. A startup option is available to
make CRON lock the log file during access, allowing several
workstations on a network to run CRON with a central logfile on the
server.
CRON works well with DESQview. Under DESQview, the background operation
of UNIX cron can be emulated by letting CRON run by itself in a (small)
window. Indeed, CRON was originally developed for use with DESQview.
See chapter 7 for instructions on using CRON with DESQview.
Although based on UNIX cron, CRON is developed from scratch and
contains no proprietary code.
CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring
CRON User's Guide Rev. 10-21-90 Page 2
1.2 Shareware
CRON is shareware (aka. User Supported Software). This means that you
may freely use CRON for a reasonable evaluation period. You may also
freely distribute CRON11.ZIP in unmodified form, to BBS'es or
otherwise.
If, after a reasonable evaluation period, you find CRON useful, I would
appreciate a contribution. NOK 150 (USD 25) suggested.
All the usual disclaimers about damages, fitness for any particular
purpose and all that apply. In brief, you use CRON at your own risks
and perils.
The contents of the CRON12.ZIP archive (i.e. CRON.EXE, CRONTAB,
CRON.DOC, LOGCHECK.EXE and CDD.EXE) are Copyright (C) 1990 by Tron
Hvaring.
1.3 Acknowledgements
Thanks to Thomas Wagner, Berlin, Germany for his EXEC routines (public
domain software, available as EXEC22.LZH on many BBS'es), on which
CRON's swap logic is based, and to Borland International for their
splendid debugger.
1.4 System Requirements
CRON runs on any IBM PC compatible computer under the DOS operating
system, version 3 or later. CRON requires a minimum of 44KB of free
memory to load, more for large CRONTABS.
1.5 Feedback
Your comments, suggestions and bug reports are most welcome. Since CRON
implements all the features of UNIX cron that make sense in a DOS
environment, new functionality is not likely to be added if not
sollicited by users. Bug reports, on the other hand, is a different
story.
CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring
CRON User's Guide Rev. 10-21-90 Page 3
2 INSTALLATION
2.1 Archive Contents
This archive should contain the following files:
- CRON.EXE, the executable program
- CRON.DOC, this document
- CRONTAB, annotated sample crontab
- LOGCHECK.EXE, let CRON control its log size
- CDD.EXE smarter CHDIR command
2.2 Installing CRON
Copy CRON.EXE to a directory in the DOS PATH (e.g. c:\bin).
Create a directory for CRON's use, for example C:\CRON.
This directory should be used for crontabs and log files.
Create your crontab using the supplied CRONTAB as a template. Read the
rest of this document for more information about crontabs. Put your
crontab in the directory you created.
2.3 Setting up CRON's environment
CRON recognizes several environment variables. These are:
CRONTAB if set, CRON assumes it contains the name of a file that is
to be used as the crontab. This can be overridden on the
command line. Typically, this environment variable will
contain C:\CRON\CRONTAB.
CRONLOG required if you want CRON to log its operations. Set to the
name of the logfile (e.g. C:\CRON\CRONLOG). Note that
CRONLOG must point to a fully qualified file name,
including drive/path. This is required since the commands
that CRON execute may change the logged drive and/or
directory.
TZ indirectly consulted by the time management functions of
the run-time library. If you live in a country that uses
daylight savings, TZ must be set for CRON to operate
correctly when the daylight savings period changes (twice a
year). Syntax is:
TZ=
where and *must* be three- character upper-case strings, and is a CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 4 signed number, positive westwards and negative eastwards relative to Greenwich. The actual contents of the character strings is irrelevant -- only their presence count. A correct value for Norway is TZ=CET-1CDT whereas a correct value for the UK is TZ=GMT0GDT If your country does not practice daylight saving, omit the last string, e.g. TZ=CET-1 if Norway hadn't practiced daylight saving. TMP if CRON is run in swap mode, it will swap most of itself out of memory when executing commands. By default, CRON will swap to a temporary file in the directory named by the TMP variable, or in the current directory if the TMP directory does not exist. If you have a RAM disk with 50- 70K of free space, set TMP to the name of directory on this RAM disk. The directory used for swapping can be overridden on the command line. COMSPEC when CRON needs to spawn COMMAND.COM, it will use the name contained in this variable, which is normally C:\COMMAND.COM. Other shells, like 4DOS, can be used by setting COMSPEC appropriately. Setting these environment variables allows you to start CRON with the appropriate environment by simply typing CRON. Here's a selected part of my AUTOEXEC.BAT: SET CRONTAB=d:\cron\crontab SET CRONLOG=d:\cron\cronlog SET TMP=m:\tmp SET TZ=CET-1CDT 2.4 Set Your Clock CRON will not operate as expected if the DOS date and time are not set correctly. In particular, remember to update your clock when crossing daylight savings zone boundaries. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 5 3 USING CRON 3.1 Command-line Summary CRON is started as follows: CRON [option] [option] ... As a special case, entering "CRON ?" will display an option summary and terminate. The available options are: -c tab -- override CRONTAB name -n -- no log -s -- swap mode -e -- swap to LIM/EMS memory if possible -d dir -- swap directory override -v -- verbose mode -L -- lock CRONLOG during access if on network drive 3.2 Crontab override -- the '-c tab' option This option overrides the name that CRON will use for the crontab. 'tab' must be the name of an existing file. Full drive/path syntax or relative syntax may be used. In the absence of this option, CRON will look for the crontab as follows: - if the CRONTAB environment variable is set, use that name - otherwise, look in the directory that was current when CRON was started for the file name "CRONTAB". CRON will complain and abort if it cannot find a crontab. Example (friday afternoon): cron -c d:\cron\weekend Note that CRON only reads the crontab at startup. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 6 3.3 Disable logging -- the '-n' option If CRON is set up for logging, this option disables logging. If CRON would not have logged anyway the option is ignored. Logging is only done if the environment variable CRONLOG is set to a fully qualified filename (i.e. with full drive/path syntax). CRON will complain if CRONLOG is set but does not point to a fully qualified filename. 3.4 Swap Mode -- the '-s', '-d dir' and '-e' options CRON may optionally swap most of itself out of memory when executing other commands. This feature is enabled by entering the -s option. CRON will by default swap to a temporary file, either in the TMP directory if set, or in the directory that was current when CRON was started. The -e option will make CRON try to swap itself to LIM/EMS memory, if present and available in sufficient quantities. See chapter 7 for a discussion of memory requirements. If EMS swapping is not possible, CRON reverts to disk swapping. The '-d dir' option will make CRON swap to a temporary file in the directory 'dir' instead of the standard places described above. CRON complains if it sees -d or -e but not -s, and if 'dir' is not a valid directory. 3.5 Verbose mode -- the '-v' option This option requires that an ANSI driver be present in your system, e.g. ANSI.SYS, or DVANSI.COM under DESQview. The effect of -v is that CRON maintains a real time display showing the next command scheduled for execution, the time it will be executed, and the time left (in seconds) until the command is executed. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 7 3.6 Locking the logfile -- the '-L' option If this option is entered, CRON will lock byte 0 of the logfile before accessing it, using the DOS 3.1 locking calls. CRON uses the IOCTL Is Redirected Handle call to determine if the logfile is on a network drive. Your DOS version must support this call (DOS function 44H, subfunction 0AH) for logfile locking to work. Most networks support the DOS 3.1 locking calls. CRON has also been tested and found to work fine on a Novell NetWare network. If your network does not support the way CRON goes about locking the logfile, CRON will still work but will simply disable logfile locking. 3.7 Stopping CRON CRON is stopped by typing ESC. CRON reminds you of this at startup. 3.8 Startup Information When CRON starts, it will print a banner consisting of the program name, version, copyright, memory available after CRON has processed the crontab and grabbed what it needs, and a reminder that you should hit ESC to stop CRON. If CRON believes that it runs under DESQview, it will print the additional line '(DESQview detected)'. In verbose mode, CRON will then print information about the first command to execute, and start its real-time second countdown. If this information looks funny (displaying left arrows and '[' characters) you don't have an ANSI driver resident. Put the line DEVICE=[drive:\path\]ANSI.SYS in your CONFIG.SYS file, or load DVANSI.COM before starting CRON if running under DESQview. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 8 4 THE CRONTAB IN DETAIL 4.1 Syntax Summary CRONTAB is a regular ASCII text file that can be created by any editor or word processor in non-document mode. Lines containing a '#' character in column 1, and blank lines, are ignored (useful for commenting crontabs). All other lines are interpreted as CRONTAB ENTRIES. A CRONTAB entry has the following format: minute hour day month day-of-week command Fields are separated by any number of tabs or spaces. No tabs or spaces are allowed inside the first 5 fields. Maximum line length is 512 characters including the trailing CR/LF pair. 4.2 The Date and Time fields These fields can have the following forms: * all legal values i,j,k sequence of values i-j inclusive range of values The sequence and range forms may be combined, as in 1,3,5,7-9,11,13-17,19 An asterisk '*' overrides any other value in a field. Thus 1,3,*,5,7 is equivalent to * Legal ranges for the different fields are as follows: minute -- 0..59 hour -- 0..23 (24-hour clock) day -- 1..31 (must be consistent with month) month -- 1..12 day-of-week -- 0..6, 0 = Sunday, 1 = Monday etc. CRON detectes values that are out of range, and impossible dates (like February 31.). CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 9 The actual execution times computed by CRON is the largest matching set of times. This is best explained by the following example: 54 6 1,15 * 1 doreport means that the command 'doreport' will be executed at 06:54 on the 1. and 15. of every month (month = '*'), AND on each monday (day-of-week = 1). If the 1. or 15. falls on a Monday, 'doreport' will not be executed twice. The extremes in terms of periodicity are: * * * * * dooften -- executes 'dooften' every minute 1 0 1 1 * calendar -- executes 'calendar' at 00:01 each January 1. 4.3 The Command Field The 'command' field of a CRONTAB entry consists of one or more COMMAND LINES, separated by semicolons ';'. If the command field contains only one command line, it should not be terminated by a semicolon. A COMMAND LINE obeys the following syntax: [~][!]DOS command line i.e. an optional '~' character, followed by an optional '!' character, followed by a regular DOS command line. Thus a command field looks like [~][!]command line;[~][!]command line;[~][!]command line.... or [~][!]command line The '~' character means 'NOSWAP'. It means that CRON should not swap itself out when executing this command, even if swapping is enabled. If swapping is disabled, the character is ignored. This feature is useful for small commands that require modest amounts of memory. If both '~' and '!' are entered, '~' must precede '!'. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 10 The '!' character is a synonym for %COMSPEC% /C, i.e. the contents of the environment variable COMSPEC, followed by the string " /C ". Thus the command lines !dir and COMMAND /C dir are equivalent, provided COMSPEC points to COMMAND.COM. '!' (or its synonym) is *required* for COMMAND.COM internal commands, like DIR, DEL and CD. '!' (or its synonym) is optional for executable programs, including .BAT files. If your command uses redirection (i.e. <, >, >> or |), '!' is required since redirection is handled by COMMAND.COM. Otherwise it should not be used, as it adds no functionality except consuming a few K of additional memory. Thus the command line sort outfile will not work as expected, but !sort outfile will. Note that CRON knows about .BAT files and will spawn COMMAND.COM internally for them. Therefore, the '!' prefix is not needed for .BAT files. When locating the command to execute, CRON follows the standard DOS algorithm: first look in the current directory, then in each directory along the PATH, respecting the search order for .COM, .EXE and .BAT files. Thus CRONTAB command lines may be entered exactly as if you were at the DOS prompt, except for the '!' prefix (which is implicit when at the DOS command line). CRON sets the logged drive and directory to their startup values (i.e. the drive and directory that were current when CRON started) before executing a CRONTAB entry. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 11 If an entry contains multiple command lines, the logged drive and directory are not reset between command lines. This allows entries such as: 57 5 1,15 * * ~!d:;~!cd \acct\dbase;misreport assuming that the program 'misreport' expects to be run from the 'D:\ACCT\DBASE' directory. The enclosed file CRONTAB contains several commented CRONTAB entries. See chapter 9 for a description of the enclosed utilities that are useful in CRONTAB entries. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 12 5 THE CRONLOG IN DETAIL 5.1 General Description The optional CRONLOG is a text file produced by CRON where all its operations and their results are logged. CRONLOG is a plain ASCII text file with highly structured lines. Cronlogs are suitable for automatic processing, for example with AWK or similar utilities. The cronlog is always opened in APPEND mode, so it is ever-increasing. The utility LOGCHECK.EXE (documented later) can be used to control the size of the cronlog. CRON produces a log entry when: - CRON is started - CRON is stopped - CRON starts to execute a CRONTAB entry - CRON has finished to execute a CRONTAB entry - CRON starts to execute subsequent command lines in a multi- command entry - CRON has finished to execute a command line in a multi-command entry. Entries have the following general format: 5.2 Starting And Stopping CRON These lines are as follows: !cron started at Fri Oct 19 13:22:35 1990 !cron stopped at Fri Oct 19 13:22:51 1990 No further comments should be necessary. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 13 5.3 Start and Stop of CRONTAB Entry Processing When CRON starts executing a CRONTAB entry, it produces a log record starting with the character '>'. A typical entry is as follows: > 'mapmem -v' Fri Oct 19 13:43:00 1990 meaning that the command field 'mapmem -v' started to execute on the indicated date and time. When the command returns, CRON produces a log entry starting with the '<' character, as follows: < 'mapmem -v' Fri Oct 19 13:43:00 1990, rc = 0 meaning that the command 'mapmem -v' executed until the indicated date and time (in this example, for less than 1 second), and returned with an exit code 0 ('rc = 0'). CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 14 5.4 Logging Multi-Command Execution For CRONTAB entries containing multiple command lines, CRON produces a sequence of records bracketed by a '>' entry, marking the start of the entry as a whole, and a '<' entry, marking the end of the entry as a whole. Between these entries, a pair or '>>' (start of command) and '<<' (end of command) is produced for each command line in the entry, including the first. The text of the '>' and '<' entries contain the entire command field. The text of the '>>' and '<<' entries contain the individual command lines, *without* any '!' or '~' prefix. These prefixes appear in the bracketing lines, though. A sample sequence is shown below, corresponding to the CRONTAB entry 54 16 * * * !d:;!cd \cron;mapmem -v > '!d:;!cd \cron;mapmem -v' Fri Oct 19 16:54:00 1990 >> 'd:' Fri Oct 19 16:54:00 1990 << 'd:' Fri Oct 19 16:54:00 1990, rc = 0 >> 'cd \cron' Fri Oct 19 16:54:00 1990 << 'cd \cron' Fri Oct 19 16:54:00 1990, rc = 0 >> 'mapmem -v' Fri Oct 19 16:54:00 1990 << 'mapmem -v' Fri Oct 19 16:54:01 1990, rc = 0 < '!d:;!cd \cron;mapmem -v' Fri Oct 19 16:54:01 1990, rc = 0 Exit codes are only produced for '<' and '<<' entries. See the next chapter for a discussion of how to interpret these codes. Some '<' and '<<' entries may contain the string "*** FAILED ***". This means that an error occured. See the next chapter for an interpretation of such entries. In a bracket '<' line, the 'rc = n' field has the same value as the last sub-command that was executed. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 15 6 ERROR HANDLING 6.1 General Considerations Errors may occur for several reasons: - CRON does not have enough resources to run - CRON may be unable to locate or spawn a command - a critical error can hit CRON (logfile disk full, swap error) - the spawned command can fail - a critical error can hit a spawned command - a spawned command may encounter an internal exception requiring user intervention (i.e. the command prompts for keyboard input). If a critical error occurs -- either inside CRON or in a spawned command -- you are simply out of luck, since the infamous 'Abort, Retry, Ignore' requires user intervention (i.e. keyboard input). I considered trapping critical errors within CRON, but decided against it. Since CRON is typically run on an unattended system, and since CRON cannot know whether or not a spawned command has put the system into an unstable state, we cannot be quite sure that a 'disk full' error really means that the disk is full. To prevent disaster we simply let the standard DOS error handling take over, suspending everything until a human can take over. This is also known as the 'better safe than sorry' strategy. CRON relies on the fact that a spawned command will eventually return. If the command decides it wants keyboard input, and no one is around, CRON will be suspended until someone comes around to hit the keyboard. The net effect of a critical error hitting a spawned command is the same. The bottom line is that you should make sure no critical errors will occur when leaving CRON in charge of an unattended system. Specifically, make sure that all required peripherals are online, that any addressed printers are online and have enough paper, et cetera, et cetera. Also, make sure that spawned commands are started in such a way that they won't ever require keyboard input. Perhaps one day I'll understand what is so critical about a printer being out of paper, and why that condition is handled in the same way as a hard disk CRC error. Or perhaps I won't. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 16 6.2 Failure to Spawn a Command CRON may fail trying to spawn a command. This is reflected by a log entry of the '<' or '<<' variety, with 'rc = -1'. If swapping is not enabled, an additional 'errno = n' is appended to the entry. See chapter 8 for interpretation of errno values. If swapping is enabled, 'rc = -1' always means that CRON could not locate the executable file. This may be caused by: - you forgot to prefix a COMMAND.COM internal command with '!' - the command does not exist in the current directory, nor in any directory in the current PATH. If a command name is given without an extension, CRON will try .COM, .EXE and .BAT exactly like COMMAND.COM does. If a '!' style command returns an exit code of -1, it means that the command interpreter itself failed to load. This is normally a serious condition, with possible causes: - the command named by COMSPEC has disappeared or is no longer in the DOS PATH - the COMSPEC environment variable has been corrupted - the PATH environment variable has been corrupted If swapping is not enabled, 'errno' contains further information. If swapping is enabled, one of the three causes above apply. 6.3 A Spawned Command Fails This is indicated by an exit code in the range 0..255. It means that CRON could spawn the command, and that the command itself returned a non-0 exit code when issuing the DOS TERMINATE call. CRON's actions depend on whether or not the current entry contains multiple commands. If the command was the only command in the CRONTAB entry, CRON simply records the exit code in the log (if enabled) and proceeds to schedule the next command. The philosophy behind this is that a failure in one crontab entry should not influence the operation of other, possible unrelated, crontab entries. If the command was part of a multi-command entry, CRON assumes that all commands in the entry are somewhat interdependent and therefore aborts execution of remaining commands in the entry, logging this fact if logging is enabled. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 17 The CDD.EXE utility (documented in a later chapter) is a more intelligent alternative to COMMAND.COM's builtin CHDIR command. The crontab entry 38 04 * * * ~cdd d:\acct\dbase;misreport will first change the logged drive and directory to 'D:\ACCT\DBASE', without swapping CRON, and then execute the command 'misreport'. Since 'misreport' obviously wants to be run from this drive/directory, we had better not run it if the 'cdd' command fails. So, if cdd returns a non-0 exit code, 'misreport' is skipped and CRON proceeds to schedule the next entry after logging the failure. 6.4 Other Internal CRON errors If a swap file error occurs, CRON will report an error code of 256 (rc = 256) for the appropriate '<' or '<<' entry and will disable swapping for all commands thereafter. This may cause failure of other commands that need so much memory that they cannot coexist with CRON in memory. Error codes starting from 768 and upwards are specific to the swapping interface to the EXEC function, and are documented later. 6.5 Exit Codes and COMMAND.COM COMMAND.COM is too dumb to return the exit code of a command that it spawns, even with the /C switch. Thus, when CRON executes a '!' entry or a .BAT file, it will receive an exit code 0 provided COMMAND.COM itself could be spawned, but the exit code from the actual command is lost even if it was non-0. Thus the following crontab entry may give surprising results: 12 7 * * * !z:;!cd \absent;!XXXXXXXXXXXXX CRON will happily spawn all three commands, since spawning COMMAND.COM succeeds. COMMAND.COM will print something like 'Bad command or file name', but will still return an exit code of 0. Thus all three commands -- which failed -- show up with 'rc = 0' in the cronlog, since COMMAND.COM lies about the results. 4DOS or some other more intelligent shell may handle this in a better way. For multi-command entries where changing drive and path is crucial, use the supplied CDD.EXE utility instead of "!d:;!cd \path" constructs. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 18 7 ADVANCED TOPICS 7.1 Resource Requirements CRON requires 44 KB of memory, plus up to 1K per 16 crontab entries. The number of crontab entries should be rounded up to the nearest multiple of 16. This is a worst-case estimate; most CRONTAB entries require less than 64 bytes. When swapping, CRON leaves 1.1K of itself -- plus the size of its environment -- in memory, swapping out the rest. When swapping to disk, CRON therefore needs (size of resident CRON - 1.1K + pad to cluster boundary + directory overhead) bytes of disk space, typically less than 64K bytes. When swapping to EMS, CRON requires (size of resident CRON - 1.1K + pad to nearest 16K boundary) bytes, typically 3 pages = 48K bytes. For very large CRONTABS (several hundred entries) CRON may require 4 EMS pages, i.e. 64K bytes. When swapping to disk, CRON uses 1 file handle which is left often across the EXEC call, reducing the spawned command's handle space from 20 to 19. Similarly, when swapping to EMS, CRON uses 1 EMS handle which is kept across the EXEC call. CRON only needs EMS and disk space when a spawned command is actually executing. Between commands (i.e. when CRON is waiting for the next command to execute), no EMS or disk space is used. CRON hooks no interrupt vectors except those hooked by the run-time library, and does not use floating point. 7.2 Using CRON with DESQview CRON works very well with DESQview. If you use DESQview, chances are that you have EMS in your system. If so, use the -s -e options to CRON for best results. CRON detects DESQview at startup. When executing its idle loop (i.e. waiting to execute the next command), CRON issues the 'give up time slice' DESQview API call. (In command line operation, CRON issues Int 28H calls instead). CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 19 CRON is generally well behaved: all output is via DOS, input is via BIOS keyboard calls. Does not use floating point, can (should!) run in the background, does not use serial lines, does not require a floppy disk. Note that CRON should not be swapped out by DESQview, because of its real-time nature. Having DESQview swap CRON would invalidate CRON's timing function. So, when designing a DESQview profile for CRON, you should think more about the programs you are spawning from CRON than about CRON itself. For example, if you spawn a telecommunications program (which is a natural for CRON), you should tell DESQview about which port it uses. Also, if a spawned program needs EMS memory, the amount should be ADDED to amount required by CRON if CRON is swapping to EMS. The previous subsection states the memory resources needed by CRON in its different operational modes. These should be added to whatever is required by spawned programs. 7.3 CRON Technical Information CRON is written in C and assembler and compiled with Turbo C++ (ANSI C compiler mode) and TASM 2.0. The Compact memory model is used, allowing an unlimited CRONTAB size subject to memory constraints. Because of the way Turbo C sets up DGROUP, CRON actually uses LESS memory in the Compact model than in the Small model, for crontabs up to 2-300 entries. The CRON source code is around 2500 lines, including comments. CRON uses only documented DOS and BIOS calls. All EMS access is via interrupt 67H, using the approved methods to detect the presence of an EMS manager. 7.4 Differences between CRON and UNIX cron There are two major differences between CRON and UNIX cron: - UNIX cron runs in the background - UNIX cron executes commands concurrently, while CRON executes commands sequentially. Under UNIX, two commands can be started by cron at the same time (well, almost). Under DOS, two commands scheduled to execute at the same time will execute one after the other, and the order of execution is random. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 20 Since UNIX cron runs in the background, and concurrently with the commands it spawns, a spawned command can never suspend cron. As described above, this may well happen with CRON in some cases. The background nature of UNIX cron can be emulated to some extent by running CRON under DESQview. Concurrency it not possible, however. With CRON, a command can be delayed if the previous command executes for a long time, i.e. past the time that the next command was due to execute. All commands will be executed, though. UNIX cron always starts commands at the scheduled times. Some of the more esoteric fields of the UNIX cronlog have been skipped, such as PID's of commands. The UNIX 'crontab' utility is of limited use under DOS and is not implemented. The LOGCHECK.EXE utility performs about the same actions as the UNIX /etc/logchecker shell script. UNIX cron reads all files in the /usr/spool/cron/crontabs directory as crontabs when it starts up -- this is the central repository of all user's crontabs. Since DOS's multiuser capability is somewhat limited, this feature was not deemed necessary. Also, hard-coded directory names and excessive use of environment variables are not popular in DOS circles. UNIX cron writes its logfile in the /usr/lib/cron directory. CRON's logfile is defined by the CRONLOG environment variable. UNIX cron re-reads its crontabs at run time if a crontab is modified by the 'crontab' utility. With CRON, you stop CRON, modify the crontab and restart CRON to achieve the same effect. The command-line options to CRON are not available nor useful under UNIX. The '~' and '!' command prefixes are specific to CRON and are not available (nor meaningful) with UNIX cron. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 21 8 REFERENCE SECTION 8.1 Error Messages CRON can complain about various things, at startup and later. All error output is sent to stdout (i.e. DOS handle 2). Any startup error, and some other errors, make CRON terminate. The following list describes the errors (in no particular order): cdd("dirname") failed CRON failed to do an internal drive/directory change. Usually means disk failure, or a spawned command has wreaked havoc in your system. This error can occur after each spawned command. No memory for crontab CRON failed to allocate dynamic memory for loading the crontab. This means that your crontab is *very* large or that you have very little memory in your system. 'command' : illegal date The crontab entry containing 'command' specifies an illegal date, for example February 31. Correct the crontab entry. Syntax: 'entry' The crontab line containing 'entry' does not conform to crontab entry syntax rules. Correct the offending line. CRONTAB is empty No entries were found in crontab. 'file': cannot open CRON could not open the named file. File probably does not exist. 'name': not a directory The specified 'name' is not a directory (swap mode). CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 22 Unable to locate CRONTAB Either the file name pointed to by the CRONTAB environment variable is invalid, or the file "CRONTAB" was not found in the startup directory. 'CRONLOG=name' : not fully qualified The environment variable CRONLOG contains a name that is not a fully qualified filename. 'CRONLOG=name' : cannot open CRON was unable to open the file named by the CRONLOG environment variable. Either the file exists and is read-only, or the name specifies a directory, or the network denied create or write access to the file. (DESQview detected) Not an error message, but a startup message stating that CRON believes that it is running under DESQview. 8.2 Exit Codes Some exit codes (shown in the cronlog as 'rc = nn') have slightly different interpretations when running CRON in swap or non-swap mode. 8.2.1 Common Exit Codes All exit codes in the range 0..255 are actual exit codes from spawned commands. Their interpretation is specific to each actual command. CRON does not attempt to interpret these codes except that in a multi- command entry, the remaining commands in the entry will be skipped if a command returns a non-0 exit code, as explained earlier. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 23 8.2.2 Swap Mode In swap mode, interpret exit codes as follows: -1 named command not found. Either the command is actually non-existent, or you forgot to prefix a COMMAND.COM internal command with '!' 0..255 see 8.2.1 256 swap file error. CRON switches swapping off permanently and continues execution. 770 DOS EXEC: file not found 771 DOS EXEC: path not found 772 DOS EXEC: too many open files 773 DOS EXEC: access denied 776 DOS EXEC: not enough memory to load command 778 DOS EXEC: environment is corrupt 779 DOS EXEC: bad format for .EXE file (.EXE file is corrupt) 8.2.3 Non-Swap Mode In non-swap mode, interpret exit codes as follows: -1 spawn failure, errno gives further information 0..255 see 8.2.1 For -1, errno can take one of the following values: 2 ENOENT: path or file not found 8 ENOMEM: not enough memory to spawn command 19 EINVAL: illegal argument 20 E2BIG: argument list is too long 21 ENOEXEC: .EXE file format error 8.2.4 RC = -1 for '!' Commands If a command prefixed with '!' returns with 'rc = -1', it means that CRON was unable to spawn the command interpreter, i.e. the program named by the COMSPEC environment variable. This is a serious error. Some possible causes are: - the COMSPEC environment variable has been corrupted - the PATH has been corrupted - the program named by COMSPEC (e.g. C:\COMMAND.COM) has disappeared. Look out for viruses. - not enough memory to spawn command interpreter. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 24 9 UTILITY PROGRAMS 9.1 CDD.EXE CDD (for "change drive and directory") is a smarter replacement for DOS's CHDIR (CD) command. Since CDD is an .EXE file, it will return an exit code != 0 if it was unable to switch drive and/or directory. USE: cdd [d:][\path] Exit codes: 0 -- success 1 -- could not switch drive 2 -- could not change directory 3 -- bad command line syntax CDD is small, so I recommend using the '~' command prefix when using CDD in crontabs. Typing "CDD ?" gives a command syntax reminder. 9.2 LOGCHECK.EXE CRON usually produces large logfiles. To avoid excessive log sizes, put a call to LOGCHECK in your crontab, with a period depending on how much you use CRON and the execution frequency of your crontab entries. USE: logcheck [-s maxsize] [-L] where 'maxsize' is the decimal number of kilobytes that you want your logfile not to exceed. If no 'maxsize' is entered, LOGCHECK assumes a value of 32. Use -L if you want LOGCHECK to lock the logfile when it operates (similar to CRON's -L option). If LOGCHECK finds that your current cronlog exceeds 'maxsize' it will perform the following actions: -- copy the current cronlog to a file with the same name but with extension 'old'. For example, if your cronlog is named 'CRONLOG.CUR', its current contents will be copied to 'CRONLOG.OLD'. If your cronlog is named 'CRONLOG.OLD', the copy will be named 'CRONLOG.OL2'. Any existing file with the modified name will be destroyed. The copy is made in the same directory as the cronlog. -- truncate the cronlog to 0 size, then add the following entry: '!logswap '. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 25 The following crontab entry will check your network cronlog daily, making sure it doesn't become much larger than 64K: 13 5 * * * ~logcheck -s 64 -L Exit codes from LOGCHECK: 0 -- successful log swap 1 -- no action (log smaller than maxsize) 2 -- could not swap log (disk error, access denied) 3 -- CRONLOG environment variable not found. 4 -- bad command line syntax Typing "LOGCHECK ?" gives a command syntax reminder. Caveat: LOGCHECK can only check the log when it is activated. Thus between invocations, the log can grow to a size much larger than 'maxsize' if there is a lot of CRON activity going on. Select LOGCHECK periodicity according to your crontab. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring CRON User's Guide Rev. 10-21-90 Page 26 10PROGRAM HISTORY Version Date Comments ----------------------------------------------------------------------- 0.0 - 1.0 10-19-90 Internal versions 1.1 10-20-90 First public release 1.2 10-21-90 Benign bug fixed: in the absence of the -L option, a file handle was needlessly kept open permanently. Harmless, but wasteful. Also, CRON.DOC stated that CRON would swap to the current directory if no TMP variable and if no -d option. This is wrong. CRON will swap to the directory that was current when CRON started under these conditions. LOGCHECK.EXE always unlocked the logfile even if locking was not specified. CRON User's Guide Rev. 10-21-90 (C) 1990 Tron Hvaring