old-www/LDP/LG/issue54/tag/14.html

377 lines
14 KiB
HTML

<!--startcut ======================================================= -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<META NAME="generator" CONTENT="lgazmail v1.3D.j">
<TITLE>The Answer Guy 54: Cron</TITLE>
</HEAD><BODY BGCOLOR="#FFFFFF" TEXT="#000000"
LINK="#3366FF" VLINK="#A000A0">
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<P> <hr>
<!-- *** BEGIN navbar *** :::::::::::::::::::::::::::::::::::::::::::::::: -->
<p align="center">
<A HREF="../lg_bytes54.html"><IMG ALT="[ Prev ]"
SRC="../../gx/navbar/prev.jpg"
WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A>
<IMG ALT="" SRC="../../gx/navbar/left.jpg"
WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom" >
<A HREF="../index.html"><IMG ALT="[ Table of Contents ]"
SRC="../../gx/navbar/toc.jpg"
WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A>
<A HREF="../../index.html"><IMG ALT="[ Front Page ]"
SRC="../../gx/navbar/frontpage.jpg"
WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A>
<A HREF="../../faq/index.html"><IMG ALT="[ FAQ ]"
SRC="../../gx/navbar/faq.jpg"
WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A>
<IMG ALT="" SRC="../../gx/navbar/right.jpg"
WIDTH="15" HEIGHT="45" ALIGN="bottom" >
<A HREF="../lg_tips54.html"><IMG ALT="[ Next ]"
SRC="../../gx/navbar/next.jpg"
WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A>
<!-- *** END navbar *** :::::::::::::::::::::::::::::::::::::::::::::::::: -->
</p>
<P> <hr> <P>
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<center>
<H1><A NAME="answer">
<img src="../../gx/dennis/qbubble.gif" alt="(?)"
border="0" align="middle">
<font color="#B03060">The Answer Guy</font>
<img src="../../gx/dennis/bbubble.gif" alt="(!)"
border="0" align="middle">
</A></H1>
<BR>
<H4>By James T. Dennis,
<a href="mailto:linux-questions-only@ssc.com">linux-questions-only@ssc.com</a><BR>
LinuxCare,
<A HREF="http://www.linuxcare.com/">http://www.linuxcare.com/</A>
</H4>
</center>
<p><hr><p>
<!-- endcut ======================================================= -->
<!-- begin 14 -->
<H3 align="left"><img src="../../gx/dennis/qbubble.gif"
height="50" width="60" alt="(?) " border="0"
>Cron</H3>
<p><strong>From Drew Jackson on Sun, 14 May 2000
</strong></p>
<!-- ::
Cron
~~~~
:: -->
<P><STRONG>
Dear sir:
</STRONG></P>
<P><STRONG><BLOCKQuote>
I have recently installed an anti-virus software program that is
</BLOCKQuote></STRONG></P>
<P><STRONG>
executed from the command-line. I would like for this service to run at
regular intervals. (i.e. every 2 hours)
</STRONG></P>
<P><STRONG>
I am using a <A HREF="http://www.redhat.com/">Red Hat</A> 5.2 based platform without GUI support.
</STRONG></P>
<P><STRONG>
Thank you for your time and effort.
</STRONG></P>
<P><STRONG>
Sincerely,
Drew Jackson
</STRONG></P>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
>
Short answer: use cron (the UNIX/Linux scheduling daemon/service).
</BLOCKQUOTE>
<BLOCKQUOTE>
The easiest way to do this would be use a text entry to
the <TT>/etc/crontab</TT> file that would look something like:
</BLOCKQUOTE>
<blockquote><pre>0 */2 * * * root /root/bin/vscan.sh
</pre></blockquote>
<BLOCKQUOTE>
(Obviously you'd replace the filename <TT>/root/bin/vscan.sh</TT> with
the actual command you need to run, or create a vscah.sh
shell script to contain all of the commands that you want
to run).
</BLOCKQUOTE>
<BLOCKQUOTE>
This table consist of the following fields: minute, hour,
day of month, month, day of week, user, command. Each of
the first five fields is filled with numerics, from one or
zero. So the minutes field is 0-59, from the first to the
last minute within any hour. The "*" character means "every"
(like in filename globbing, or "wildcard matching"). The
hours are 0-23, the dates are from 1-31, etc. The syntax of
this file allows one to specify ranges (9-17 for 9:00 am to
5:00 pm for example), lists (1,15 for the first and fifteenth
--- presumably one you'd use for dates within a month), and
modulo patterns (such as the one in my example, which means
"ever other" or "ever even"). So, to do something every
fifteen minutes of every other day of every month I'd
use a pattern like: '<tt>*/4 * */2 * * user command</tt>'.
</BLOCKQUOTE>
<BLOCKQUOTE>
The day of week and the months can use symbolic names
and English abbreviations in the most common versions
'cron' utility (by Paul Vixie) that are included with
Linux distributions.
</BLOCKQUOTE>
<BLOCKQUOTE>
You can read the crontab(5) man page for details.
Note that there is a 'crontab' command which has
its own man page in section one. Since section
one (user commands) is generally searched first
--- you have to use a command like: 'man 5 crontab'
to read the section five manual page on the
topic. (Section five is devoted to text file
formats --- documenting the syntax of many UNIX
configuration files).
</BLOCKQUOTE>
<BLOCKQUOTE>
This system is pretty flexible but cannot handle some
date patterns that we intuitively use through natural
language. For example: 2nd Tuesday of the month
doesn't translate directly into any pattern in
a crontab. Generally the easiest way to handle that
is to have a crontab entry that goes off the minimal
number of times that <EM>can</EM> be expressed in crontab
patters, and have a short stub of shell code that
checks for the additional conditions.
</BLOCKQUOTE>
<BLOCKQUOTE>
For example, to get some activity on the second
Tuesday of the month you might use a contab entry
like:
</BLOCKQUOTE>
<blockquote><pre>* * * * 2 joe /home/joe/bin/2ndtuesday.sh
</pre></blockquote>
<BLOCKQUOTE>
which runs every Tuesday. If we used a pattern
like:
</BLOCKQUOTE>
<blockquote><pre>* * 7-13 * 2 joe /home/joe/bin/2ndtuesday.sh
</pre></blockquote>
<BLOCKQUOTE>
... our command would run on every Tuesday <EM>and</EM> on
each of the days of the second week of the month
(from the 7th through the 13th). This is NOT what
we want. So we use the former pattern and have a
line near the beginning of our shell script that
looks something like:
</BLOCKQUOTE>
<blockquote><pre>#!/bin/bash
# Which week is this?
weeknum=$[ $(date +%e) / 7 + 1 ]
## returns 1 through 5
[ "$weeknum" == 2 ] || exit 0
# Rest of script below this line:
</pre></blockquote>
<BLOCKQUOTE>
Of course that could be shortened to one expression like:
</BLOCKQUOTE>
<blockquote><pre>[ "$[ $(date +%e) / 7 + 1 ]" == 2 ] || exit 0
</pre></blockquote>
<BLOCKQUOTE>
... which works under 'bash' (the default Linux command
shell) and should would under any recent version of ksh
(the Korn shell). That might need adjustment to run
under other shells. This also assumes that we have
the FSF GNU 'date' command (which is also the default
under Linux).
</BLOCKQUOTE>
<BLOCKQUOTE>
Of course, if you were going to do this more than a few
times we'd be best off writing one script that used
this logic can calling that in all of our crontab entries
that needed it. For example we could have a script
named 'week' that might look something like:
</BLOCKQUOTE>
<blockquote><pre>#!/bin/bash
## Week
## Conditionally execute a command if it is issued
## during a given week of the month.
## weeks are numbered 1 through 5
[ $# -ge 2 ] || {
echo "$0 requires least two args: week number and command" 1&gt;&amp;2
exit 1
}
[ "$(( $1 + 0 ))" == "$1" ] &amp;&gt; /dev/null || {
echo "$0: first argument must be a week number" 1&gt;&amp;2
exit 1
}
[ "$[ $(date +%e) / 7 + 1 ]" == "$1" ] || exit 0
shift
eval $@
</pre></blockquote>
<BLOCKQUOTE>
... or something like that.
</BLOCKQUOTE>
<BLOCKQUOTE>
(syntax notes about this shell script: '[' is an alias for the
'test' command; '$#' is a shell scripting token that means
"the number of arguments"; '||' is a shell "conditional execution
operator" (means, if the last thing returned an error code,
do this); '1&gt;&amp;2' is a shell redirection idiom that means "print
this as an error message"; '$[ ... ]' and '$(( ... ))' enclose
arithmetic expressions (a bash/ksh extension); '$@' is all
of our (remaining) arguments; and the braces enclose groups of
commands, so my error messages and exit commands are taken
together in the cases I've shown here).
</BLOCKQUOTE>
<BLOCKQUOTE>
So this shell script basically translates to:
</BLOCKQUOTE>
<BLOCKQUOTE><BLOCKQuote>
If there aren't at least 2 command line arguments here,
complain and exit. If the first argument isn't a number
(adding 0 to any number should yield the same number)
then complain and exit. If the week number of today's
date doesn't match the in the first argument then
just exit (no complain). Otherwise, forget that first
argument and treat the rest of the arguments as a
command.
</BLOCKQuote></BLOCKQUOTE>
<BLOCKQUOTE>
(Note: cron automatically sends the owner of a job
e-mail if the command exits with a non-zero (error) value
or if it produces any output. Normally people write
the cron job scripts to avoid generating any normal output
<TT>---</TT> they either pipe the output into an e-mail, redirect
it to <TT>/dev/null</TT> or to some custom log file; and/or possibly
add 'logger' commands to send messages to the system logging
services ('syslog'). E-mail from 'cron' consists of some
diagnostics information and any output from the job).
</BLOCKQUOTE>
<BLOCKQUOTE>
In some fairly rare cases it would be necessary to wrap
the target command, or parts of it in single quotes to get it
to work as desired. Those involve subtleties of shell syntax
that are way beyond the task at hand.
</BLOCKQUOTE>
<BLOCKQUOTE>
A more elaborate version of that shell script might allow
one to have a first argument that consisted of more than
one week number. The easiest way to do that would be to
require that multiple week numbers be quoted and separated
with spaces. Then we'd call it with a command like
'week "1 3" $cmd' (note the double quotes around 1 and 3).
</BLOCKQUOTE>
<BLOCKQUOTE>
That would add about five lines to my script. Anyway,
I don't feel like it right now so it's left as an exercise
to the reader.
</BLOCKQUOTE>
<BLOCKQUOTE>
Anyway, 'cron' is one of the most basic UNIX services. It
and the related 'at' command (schedule "one time" events)
are vital system administration and user tools. You should
definitely read up on them in any good general book on using
or administering UNIX or Linux. (I personally think that they
are woefully <EM>underused</EM> judging from the number of "temporary"
kludges that I have found on systems. Hint: every time you
do something that's supposed to be a "temporary" change to
your system --- submit an 'at' job to remind you when you
should look at it again; maybe to remove it).
</BLOCKQUOTE>
<BLOCKQUOTE>
BTW: I'd suggest that you seriously consider upgrading to a
newer version of Linux. Red Hat 5.2 was one of the most stable
releases of Red Hat. However, there have been many security
enhancements to many of the packages therein over the years.
</BLOCKQUOTE>
<!-- sig -->
<!-- end 14 -->
<!--startcut ======================================================= -->
<P> <hr> </p>
<H5 align="center"><a href="http://www.linuxgazette.com/copying.html"
>Copyright &copy;</a> 2000, James T. Dennis
<BR>Published in <I>The Linux Gazette</I> Issue 54 June 2000</H5>
<H6 ALIGN="center">HTML transformation by
<A HREF="mailto:star@tuxtops.com">Heather Stern</a> of
Tuxtops, Inc.,
<A HREF="http://www.tuxtops.com/">http://www.tuxtops.com/</A>
</H6>
<P> <hr>
<!-- begin tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::-->
<p align="center">
<IMG ALT="" SRC="../../gx/navbar/left.jpg"
WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="middle" border="0">
<A HREF="../lg_answer54.html"
><IMG SRC="../../gx/dennis/answertoc.jpg" align="middle"
ALT="[ Answer Guy Current Index ]" border="0"></A>
<A HREF="../lg_answer54.html#greeting"><img align="middle"
src="../../gx/dennis/smily.gif" alt="greetings" border="0"></A> &nbsp;
<A HREF="1.html">1</A> &nbsp;
<A HREF="2.html">2</A> &nbsp;
<A HREF="3.html">3</A> &nbsp;
<A HREF="4.html">4</A> &nbsp;
<A HREF="5.html">5</A> &nbsp;
<A HREF="6.html">6</A> &nbsp;
<A HREF="7.html">7</A> &nbsp;
<A HREF="8.html">8</A> &nbsp;
<A HREF="9.html">9</A> &nbsp;
<A HREF="10.html">10</A> &nbsp;
<A HREF="11.html">11</A> &nbsp;
<A HREF="12.html">12</A> &nbsp;
<A HREF="13.html">13</A> &nbsp;
<A HREF="14.html">14</A> &nbsp;
<A HREF="15.html">15</A> &nbsp;
<A HREF="16.html">16</A> &nbsp;
<A HREF="17.html">17</A> &nbsp;
<A HREF="18.html">18</A>
<A HREF="../../tag/kb.html"
><IMG SRC="../../gx/dennis/answerpast.jpg" align="middle"
ALT="[ Index of Past Answers ]" border="0"></A></td>
<IMG ALT="" SRC="../../gx/navbar/right.jpg" align="middle"
WIDTH="14" HEIGHT="45" BORDER="0">
</p>
<!-- end tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::::-->
<P> <hr>
<!-- *** BEGIN navbar *** :::::::::::::::::::::::::::::::::::::::::::::::: -->
<p align="center">
<A HREF="../lg_bytes54.html"><IMG ALT="[ Prev ]"
SRC="../../gx/navbar/prev.jpg"
WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A>
<IMG ALT="" SRC="../../gx/navbar/left.jpg"
WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom" >
<A HREF="../index.html"><IMG ALT="[ Table of Contents ]"
SRC="../../gx/navbar/toc.jpg"
WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A>
<A HREF="../../index.html"><IMG ALT="[ Front Page ]"
SRC="../../gx/navbar/frontpage.jpg"
WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A>
<A HREF="../../faq/index.html"><IMG ALT="[ FAQ ]"
SRC="../../gx/navbar/faq.jpg"
WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A>
<IMG ALT="" SRC="../../gx/navbar/right.jpg"
WIDTH="15" HEIGHT="45" ALIGN="bottom" >
<A HREF="../lg_tips54.html"><IMG ALT="[ Next ]"
SRC="../../gx/navbar/next.jpg"
WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A>
<!-- *** END navbar *** :::::::::::::::::::::::::::::::::::::::::::::::::: -->
</p>
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
</BODY></HTML>
<!--endcut ========================================================= -->