APLawrence.com -  Resources for Unix and Linux Systems, Bloggers and the self-employed

UNIX Basics: JOB SCHEDULING


© May 2004 Steggy

By Steggy
BCS Technology Limited
Email: steggy@bcstechnology.net
Web Site: https://www.bcstechnology.net

In the UNIX or Linux environment, it is possible to asynchronously execute tasks at any desired time of the day, a feature made possible by the cron clock daemon.  In the following text we will present some general information on how to use cron and its companion at, as well as some tips on avoiding problems.  Although this discussion is geared toward the SCO OpenServer implementation of cron, the basics are applicable to all modern UNIX implementations.

CRON BASICS

Succinctly stated, cron's role is to spawn jobs in accordance with the passage of time.  cron itself is normally started at boot time when the system switches to multiuser operation and once started, never stops unless it is manually killed or the system is halted.  cron is slaved to the system clock and awakens at one minute intervals to start scheduled jobs (which are referred to as cron jobs).

When the time arrives to start a job, cron spawns a shell in which to run the job, thus allowing the job to execute independently of cron itself.  A cron job executes with the identity and privileges assigned to the system user who scheduled the job.  As a general rule, cron jobs are arranged to automatically die when they have finished their work.  However, this is not an absolute requirement.

In order to know what is scheduled to run, cron reads text files called cron tables, which authorized users may generate and maintain.  cron table maintenance is accomplished with the crontab command.  Of the various crontab invocations, crontab -e and crontab -l are most often used, the former to create or edit a cron table and the latter to display it.  On most systems, crontab -e will automatically start the vi text editor and if a cron table already exists, load it into vi.  Upon saving and exiting from vi, the new or revised file will be submitted to cron, overwriting the existing cron table.

Like other UNIX files, each cron table is owned by the user who created it, and excepting root, can only be edited or viewed by its owner.  root can edit any user's cron table with the invocation crontab -u <user> -e or display any table with crontab -u <user> -l, where <user> is a UNIX username.  A user may remove his or her cron table with the command crontab -rroot is allowed to remove anyone's cron table.


CAUTION:  The crontab -r command DOES NOT confirm your intention.  Once deleted, the cron table is gone forever.  Unless there is a compelling reason to do so, avoid editing root's cron table.




A cron table file is ordinary ASCII text and consists of one or more lines specifying what is to be executed and when.  A typical cron table line takes the general form:

min    hour    day    mon    dow    command    #comment




where min and hour define the time of day (in 24 hour format) at which execution is to commence, day defines the day of the month on which to start execution, mon defines the month in which to start execution, and dow definess the day of the week on which to start execution.  The command field specifies what is to be executed, using Bourne shell syntax, and may include arguments.  It is highly recommended you use a fully qualified filename for command, as cron normally limits its search to /bin and /usr/bin.  If command cannot be found, cron will complain by sending local mail to the owner of the cron table.

Scheduling is quite flexible.  Permissible values for the date and time fields are as follows:


min    0-59
hour   0-23
day    1-31
mon    1-12
dow    0-6 (Sunday = 0)




Scheduling values are cumulative: if you specify both a day and dow value, cron will attempt to obey both parameters.  In addition to the above values, cron understands an asterisk (*) to mean all legal values for the field where it is used, and also understands numeric ranges.  For example, if the dow parameter is 0,3,6 it tells cron to execute the job on Sunday, Wednesday and Saturday.  If the dow parameter is 1-5 it means execute the job Monday through Friday inclusive.  You could also specify 0,15,30,45 for the min field and asterisk everything else, which would cause the job to run at 15 minute intervals, starting with every hour on the hour.  If all fields are asterisks, cron will attempt to run the job at one minute intervals.

Any text following an octothorpe (#) is treated as a comment and ignored by cron.  Reasonably terse comments are recommended.  All parameters must be separated by at least one space or tab (tabbed columns are suggested for clarity).

Here's a cron table entry example:


05 00 01 01 * /usr/local/bin/archive_files #archive files


This entry will cause cron to start /usr/local/bin/archive_files at five minutes after midnight on the first day of January of each year.  The asterisk in the dow field indicates to cron that any day of the week is acceptable.  However, since an explicit month and day have been specified, the day of the week is effectively ignored.  archive_files would be a user-written shell script or program that would perform whatever processing that was required.  See the crontab man page for more information.  Incidentally, leading zeros in the numeric fields are permitted and generally help to improve the readability of the table when fields are tab-delimited.

Theoretically, it is possible to execute any UNIX script or program with an entry in a cron table.  However, the execution environment into which a cron job is spawned is very limited in scope, being determined by the parameters in the /etc/default/cron file, as well as the rights of the user owning the cron job.  In most cases, the default shell will be the Bourne shell (or bash on Linux systems) and the default path will be limited to /bin, /usr/bin and on OpenServer, /usr/lbin.  Therefore, the first thing your cron job script should do is set up a suitable environment, such as augmenting the path definition, defining a subdirectory for temporary file storage, and so forth.

As stated before, a cron job inherits the identity and access privileges of the owner of the cron table from which the job was spawned.  It is essential you understand this characteristic of cron, as you may run into trouble with your program if it is denied access to a directory or file due to ownership and access rights.  Similarly, be sure your cron job correctly sets the umask value so that any files that are created inherit the correct permissions.  As always, information about how your system implements cron can be gleaned from local man pages.

TIME FACTORS

It is important to consider the effects of daylight savings time on cron's operation.  OpenServer will reschedule any job that is supposed to run between 2:00 AM and 2:59 AM on the day when the switch is made from standard to daylight savings time.  This is because immediately following the time change the period from 2:00 AM to 2:59 AM will cease to exist.  Similarly, any job scheduled to run between 2:00 AM and 2:59 AM on the day the switch back to standard time is to occur may be run twice, as that time range will be repeated.  The best policy is to not schedule anything to run between 1:59 AM and 3:00 AM if your locale observes daylight savings time.

OUTPUT

Normally the output of any program is sent to STDOUT (standard out) and usually winds up on someone's display screen.  For jobs started by cron, STDOUT will be directed to the local mail subsystem, which means any output generated by a cron job will be mailed to the user owning the job.  If this is not desirable you should take steps to redirect your cron job's output to a file.  It is also suggested you redirect STDERR (standard error) to a file so as to be able to analyze any anomalies in your cron job's execution.

Another possibility is to E-mail your cron job's output to a remote user by piping the output to the mail command.  For example:


mycronjob | mail -s "cron job output" you@somewhere.com


ONE TIME CRON

Closely related to cron is the at command.  Like cron, at can run any job at a scheduled time.  However, at will only run the job once, unless the job reschedules itself.  at is invoked from the command line or from within a shell script.  The basic command is:

at <time>


where <time> is when to execute the job.  The above invocation will cause at to read STDIN for a list of commands to be executed at <time>.  Once you have type in a command list and have exited with Ctrl-D, the job will be submitted.

Alternatively, you could say:


at <time> < FILE


where FILE is a shell script of some sort that has been prepared from a text editor.

<time> can be in several forms, such as 12 or 24 hour clock time, a date and time, an offset to the current time (e.g., now + 5 minutes) or similar.  Again, see your local man pages for details.

As with cron, at's execution environment is limited in scope, and the rights assigned to the at job will be the same as those belonging to the invoking user.  If your at job cannot get access to something because of insufficient privileges it will complain via local mail.

SUMMARY

Use cron to execute jobs on a regular schedule (e.g., run an automatic tape backup each work night or generate end-of-month reports).  Use at to run a job once at some time in the future.  Use them both to automate your repetitive tasks!

Got something to add? Send me email.





(OLDER)    <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

->
-> UNIX Basics: JOB SCHEDULING

28 comments


Inexpensive and informative Apple related e-books:

Digital Sharing Crash Course

Take Control of Numbers

El Capitan: A Take Control Crash Course

Take Control of High Sierra

iOS 8: A Take Control Crash Course




More Articles by © Steggy



Nice beginners article! I have someonne who I am trying to teach the *nix basics to, and this will be a nice way to introduce cron. Good job!

- Bruce Garlock

Something I neglected to mention is that the at command is useful for testing scripts that will be started by cron.

--BigDumbDinosaur





Fri Mar 25 19:13:01 2005: 236   KarimGrant


64.229.186.211 (looks like spam)



Wed Jun 1 11:23:51 2005: 603   anonymous


its real gud for sumone wanting to understand basic tid bits of crons...



Fri Mar 14 12:55:21 2008: 3842   manoj


I want to learn about cron and i searched in google.This was the first link i saw in google.This site proved very useful for me.I had my ignorance in crontab removed off.Thanks!!!



Fri Mar 14 13:03:46 2008: 3843   TonyLawrence

gravatar
Glad we could be of help. Type "cron" in the search box here to find many other related articles.



Wed Apr 16 16:53:29 2008: 4043   rick


Excellent summary. Thank you.



Wed Jul 23 07:08:15 2008: 4440   Raj


This is a great summary on unix scheduling. Hats off to Steggy.
I have a query on at scheduling. Can we schedule a job precisely to run at a particular second or millisecond using at scheduler?



Wed Jul 23 11:00:52 2008: 4441   TonyLawrence

gravatar
Not on any normal system, no. To start with, the ststem itself would need to be real-time and then "at" itself would need to allow you to specify such accuracy. Some "at"'s do let you get to seconds with a "-t" flag, but unless the system is real-time, there's no guarantee that it will really run at that second.



Wed Jul 23 12:53:38 2008: 4442   BigDumbDinosaur


Can we schedule a job precisely to run at a particular second or millisecond using at scheduler?

You could do a kludge to achieve near real time execution by starting your cron job a minute before you want it to run and then execute a loop within until the system time reaches the desired job execution time. As Tony said, only a real time system can start a job at a precise moment. In the Linux/UNIX environment, scheduling is based on a number of conditions, the passage of time being but one of them. A system that is heavily I/O bound will seldom be able to run a cron job at the selected time -- usually a lag of several seconds is typical. At best you'll get within a second or two of the desired time.



Sun Nov 2 08:44:53 2008: 4715   anonymous


I Think we switch from Daylight savings Time to Standard Time at 2:00am , ie at 2:00am the clock is pushed back to 1:00am, hence the jobs scheduled between 1:00am and 2:00am may be repeated. ( and not 1:59 to 3:00 in the article)



Sun Nov 2 17:23:04 2008: 4722   BigDumbDinosaur


I Think we switch from Daylight savings Time to Standard Time at 2:00am , ie at 2:00am the clock is pushed back to 1:00am, hence the jobs scheduled between 1:00am and 2:00am may be repeated. ( and not 1:59 to 3:00 in the article)

The article doesn't say that jobs scheduled between 1:59 AM and 3:00 AM will be repeated. Please reread that section.

What does happen is that when the transition from daylight saving time occurs at 2:00 AM, the system clock is instantly retreated one hour, which means 1:00 AM occurs twice on that day. Due to a certain amount of latency inherent in all UNIX-like operating systems, cron does not awaken precisely on the minute. Therefore, when cron does awaken and examines the cron jobs table, time will have already been reset to 1:00 AM, and any 2:00 AM jobs will not be double-executed. Jobs that are scheduled between 1:00 AM and 1:59 AM will be repeated, since that time range will occur twice.

Similarly, when the transition from standard time to daylight saving time occurs, 2:00 AM will never exist, as the system clock will be instantly advanced one hour to 3:00 AM. Unless the version of cron on the system has been designed to reschedule jobs that range from 2:00 AM to 2:59 AM inclusive, they will not be executed, as that time range will not exist on the day of transition.

Therefore, the best policy is to not schedule anything to run between 1:59 AM and 3:00 AM, as the article states. If you do, you may not see the results that are expected.










Mon Nov 3 01:12:42 2008: 4729   BigDumbDinosaur


Dunno what happened above but there's a double post of my last comment. The second one is the correct one, the first looks like an editing session I broke off for a short time while answering a phone call. Tony, you sure Windows didn't somehow get mixed with this? :-)



Mon Nov 3 13:39:17 2008: 4732   TonyLawrence

gravatar
No, it's all BSD Perl.. just my goofup somewhere..



Mon Nov 3 14:09:24 2008: 4733   BigDumbDinosaur


<Wiping Brow>I was worried that Bill Gates somehow got his meathooks into your system. <Grin>



Wed Dec 3 03:50:27 2008: 4834   Joydeep


How do I schedule a job depending on certain conditions? Can Cron do that? Or, do I need some other software for that? Please let me know.

Thanks



Wed Dec 3 12:16:11 2008: 4835   TonyLawrence

gravatar
You schedule it as you would any job, and let the script/program that is run test the condition. If it doesn't match, it exits, otherwise continues on to do whatever it is supposed to do.



Wed Dec 3 15:24:23 2008: 4836   BigDumbDinosaur


How do I schedule a job depending on certain conditions?

Can you be a bit more specific as to what it is you mean by "certain conditions"? Are these conditions related to the passage of time, the amount of water in your dog's bowl, the phases of the moon, or what? Vague questions tend to result in vague answers, y'know. :-)



Fri Oct 16 19:34:49 2009: 7277   anonymous

gravatar
very helpful. Thanks!



Fri Jan 15 15:52:34 2010: 7912   Sridhar

gravatar


Hi,
How to create a cron job that will run on the last day of each month, considering the fact that a month could have 28, 29, 30 or 31 days?

Thanks,
Sridhar



Fri Jan 15 15:59:30 2010: 7913   TonyLawrence

gravatar


run on the last day of each month

Cron can't do that.

Your script, however, can test for that and exit if it is not the last day.

So - you'd set it in cron to run on the 28, 29, 30 and 31. Your script decides if it really is the last day and exits if it is not.

Or you can put each month into crontab separately and just deal with February in your script.



Fri Jan 15 18:27:18 2010: 7914   TonyLawrence

gravatar


Though I should mention that for many tasks like this, doing it in the first minute of the first day of the month is often just as good and dead simple.



Sun Jan 17 03:31:19 2010: 7919   BigDumbDinosaur

gravatar


Though I should mention that for many tasks like this, doing it in the first minute of the first day of the month is often just as good and dead simple.

That's what I'd do, run it at midnight on day one:
0   0   0   0   1  /usr/local/bin/run_my_job

run_my_job will execute one or two seconds after midnight on the first day of the month. Note that cron never actually hits the time right to the zeroth second. That's why the above is guaranteed to work.

However, if you absolutely, positively must have the job run on the last day of the month, you could create three cron jobs as follows:

0  18  0  2                28,29 /usr/local/bin/run_my_job 
0 18 0 4,6,9,11 30 /usr/local/bin/run_my_job
0 18 0 1,3,5,7,8,10,12 31 /usr/local/bin/run_my_job


The above lines determine when to run the job depending on the month and solve the problem for all months except February (I set it up to run at 1800 -- pick your time as needed).

If it's February, you'll have to analyze the year to see if it's a leap year. You can get the current four-digit year with:

current_year=`date +%Y`

the current month with:

current_month=`date +%m`

and the current day of the month with:

current_dom=`date +%d`

Once you have that information, you need to determine if the year is a leap year, that is, evenly divisible by four, unless the year is an end-of-century value (e.g., 2100, 2200, etc.), in which case you need to determine if it is evenly divisible by 400. If the year is a leap year and the day of the month is not 29, don't run the job. Otherwise, run the job. It's that simple. <Grin> Naturally, you don't do the leap year test if the month is anything other than February.

All-in-all, starting the job at midnight on the first day of the month is a lot easier.



Sun Jan 17 16:40:37 2010: 7920   BigDumbDinosaur

gravatar


In the above, there's a typo in each of the crontab examples. The third field should be * instead of 0 (zero), such as:

0   18   *   4,6,9,11   30   /usr/local/bin/run_my_job

Sorry for the confusion.



Mon Jan 25 09:17:17 2010: 7950   anonymous

gravatar


superb article



Sat May 29 06:05:50 2010: 8644   Manam

gravatar


good artical.thanks for giving good information.



Sun May 30 23:54:42 2010: 8645   BigDumbDinosaur

gravatar


Thanks for the compliments. Once in a while I manage to fool humans with my smarts routine. ::)



Sat Oct 29 04:37:09 2011: 10093   anonymous

gravatar


The page resolves my one problem.

------------------------


Printer Friendly Version

Have you tried Searching this site?

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us


Printer Friendly Version





There is no reason anyone would want a computer in their home. (Ken Olson, president, chairman and founder of DEC)




Linux posts

Troubleshooting posts


This post tagged:

Basics

Popular

Steggy



Unix/Linux Consultants

Skills Tests

Unix/Linux Book Reviews

My Unix/Linux Troubleshooting Book

This site runs on Linode