procmail
[Top] [All Lists]

Re: track error messages to limit notification

1998-11-28 06:53:21
On Sat, 28 Nov 98 06:35:21 -0500, Jerry Shenk <jas(_at_)dect(_dot_)com> wrote:
I'd like a way to have procmail process alert messages but it it gets the 
same alert every 15 minutes, only notify me on the first alert....maybe even 
<...>
has been sent out this (day, hour, half-day, etc.).  I guess probably the 
best way to handle this would be to have procmail launch a shell script 
(perl script?) when certain alerts were received.

This then, as usual, reverts to the familiar Not Really a Procmail
Question But Rather a Shell Script Question, but here goes anyway.

Let's assume you already have figured out how to determine in Procmail
whether a message is an alert of some kind. Below, I will use the
simple condition that if the Subject: begins with "alert:", this is an
alert message. Your real alert messages are probably more complicated.

So the trivial way to solve it is to just say 

    :0
    * ^Subject:[        ]*alert:
    | script-which-does-the-real-work

But we can do better -- we can actually use Procmail to do some of the
work, thereby hopefully making delivery of your typical alert message
somewhat less processor-intensive (but perhaps not). I'll only sketch
out the solution I have in mind here.

While preparing this reply, I first toyed with a solution which
involved an INCLUDERC=alert.rc where the contents of alert.rc would
depend on whether another alert had arrived in the last fifteen
minutes (an at job would be set up to switch in different files) but
this became kind of messy and is virtually hopeless to maintain if
there is more than one kind of alert you want to keep track of. So I
came up with a concept involving a cookie file instead.

The bulk of the work would still be done by the script, but you would
feed it a command line parameter containing some sort of cookie, e.g.
the From_ line of the current message, and you'd want a lock on the
script so only one copy can be running at the same time:

    :0cw:alert.lock
    * ^Subject:[        ]*alert:
    * ^\/From .*
    | script-which-does-the-real-work "$MATCH"

In the script, write the cookie (the command-line parameter) to a
file. If the file exists, overwrite. If the file doesn't exist, this
was not a repeat warning. Now schedule an at job to remove the cookie
file only if the contents of the cookie file are the same as those
given to the at job. Return status of the script is 0 for new alert, 1
for repeat. 

Now the subsequent recipes in your .procmailrc can act on the status
code of the script with the :a and/or :e flags, and do what's
appropriate.

    #!/bin/sh

    PATH=/whats:/appropriate:/for:/this:/kind/of:/job
    umask 077
    # unset noclobber etc if you might have that set somehow

    COOKIE="$1"
    COOKIEFILE="$HOME/.alert.cookie"

    test -e "$COOKIEFILE" && exitstatus=1

    echo "$COOKIE">"$COOKIEFILE"

    # test this on the command line, some at(1)s are picky about time formats
    at now+15min <<HERE
    lockfile $MAILDIR/alert.lock
    test `cat "$COOKIEFILE"` = "$COOKIE" && rm -f "$COOKIEFILE"
    rm -f $MAILDIR/alert.lock
    HERE

    exit $exitstatus

This is untested, as usual ...

If you have several independent categories of alerts, you need one
recipe, one series of at jobs, and one cookie file for each category
you want to distinguish (but the name of the cookie file could
certainly be passed in as a parameter to the script, so you can use
the same script for them all).

I suppose the at jobs which manipulate the cookie file should also
observe the same lockfile as the rest of the system. I put that in but
it will only work right if MAILDIR is set -- this makes it a bit hard
to test interactively. (Oh, just set MAILDIR by hand before testing,
and/or add something to the main script to set it to something
reasonable if it's not already set. Hint: ${MAILDIR:=$HOME/Mail})

If you don't think this sounds like a great solution, you should
perhaps switch to Perl. With Perl, it's easy enough to simply test
whether a file is older than n seconds. (This is slightly hairy in
shell scripts, unless you have an enhanced version of test(1) or like
to use find(1) for simple tasks like this -- I perceive it as too
heavy.) You could perhaps write one line to an alert log for each
alert received, and use normal log processing tools to see if it is a
repeat. 

For shell scripts, the concept of at jobs is a useful one to learn for
tasks like this. It's often simpler to run a trivial at job in fifteen
minutes than to do a lot of date parsing just to see what kind of
processing has taken place recently.

Hope this helps,

/* era */

-- 
.obBotBait: It shouldn't even matter whether    <http://www.iki.fi/~era/>
I am a resident of the state of Washington. <http://members.xoom.com/procmail/>

<Prev in Thread] Current Thread [Next in Thread>