Forwarding Alert Email
[posted 2000/03/01]
A member of pikt-users asked: "I need to forward the dead crucial processes to emails other then the one specified for Urgent alerts."
And I replied:
If you want the same alert message, header and all, to go to two or more persons, the easiest way is simply to redefine your =pikturgent with two or more addressees, for example (in macros.cfg),
pikturgent jane.russell\ howard.hughes\
Or, if you do as we do, use NIS aliases, just keep your current macro definition, for example,
pikturgent pikt-urgent
where pikt-urgent is an alias defined in your NIS map, then add the extra addressees in the NIS entry.
Or, yes, do it the way you did, defining another macro
piktfido root // fido-mail pikturgent =piktfido
(I changed "piktcrucial" to "pikturgent" in your example for consistency. I'm a bit surprised if you don't have to put a '\' before the '@' in your addresses.)
But while pondering your question, I thought of situations where you might want forwarding of alert email to one or more non-standard extra addressees. Following is another method (with variant) that you might try.
To demonstrate, I registered a new Test alert in alerts.cfg:
Test timing =piktnever mailcmd "=mailx -s 'PIKT Alert on =pikthostname: Test' pikt-test" alarms OtherMailTest
And here is OtherMailTest, variant 1:
OtherMailTest // variant 1 init status active level notice task "this is a test" input file "/etc/hosts" begin set #isopenmail = #false() rule output mail $inline if $inline =~ "loghost|localhost" if ! #isopenmail if #popen(MAIL, "=mailx -s 'test' robert.osterlund\", "w") != #err() set #isopenmail = #true() else output mail "\#popen() failure for: =mailx -s 'test' robert.osterlund\" quit endif endif do #write(MAIL, $inline) endif end if #isopenmail do #pclose(MAIL) endif
(I installed the script using 'piktc -iv +A Test +H vienna' and ran it at the command line using 'pikt +A Test'.)
This is just a toy script to demonstrate some points. It goes through /etc/hosts, and outputs every line to whoever receive(s) the alert mail as defined in 'mailcmd' in alerts.cfg. In addition, it sends lines matching either "loghost" or "localhost" to a different addressee, in this case myself. Note that only matching lines are sent; no alert header is sent (unless we write extra script code to do that).
In the script, we set and test the #isopenmail variable to #popen() and #pclose() the MAIL filehandle just once and at just the right moments. (We don't test the return value of the #pclose() call, just assuming that the MAIL filehandle was #pclose()'ed properly.)
I can see where one might want to do this sort of thing often--forwarding alert email output to additional addressees beyond what's defined in the mailcmd (or your alert addressee macros). Using the new macro feature in PIKT 1.9.0, here is one way you might do it. Following is variant 2 of OtherMailTest:
OtherMailTest // variant 2 init status active level notice task "this is a test" input file "/etc/hosts" rule output mail $inline if $inline =~ "loghost|localhost" =output_other_mail(OTHERMAIL, 'test', robert.osterlund\, $inline) endif
Much simpler than variant 1, no? And here is the =output_other_mail macro definition (in macros.cfg):
output_other_mail(F, S, R, L) // output conditional mail to addressee(s) // beyond those specified in the alert // mailcmd; we don't #pclose() the (F) // filehandle at the end, instead letting // pikt do it // (F) is the filehandle name (e.g., MAIL) // (S) is the subject (e.g., 'check this out') // (R) is the recipient (e.g., 'berto\') // (L) is the line (e.g., $inline) if ! #defined(#isopen(F)) set #isopen(F) = #false() fi if ! #isopen(F) if #popen((F), "=mailx -s (S) (R)", "w") != #err() set #isopen(F) = #true() else output mail "\#popen() failure for: =mailx -s (S) (R)" quit fi fi do #write((F), (L))
(It would be possible to complexify this macro definition to automatically determine a suitable 'F' from the supplied 'R'. Then you could call this macro supplying just three arguments--the subject, the recipient, the line. But, naw!, that's too complicated.)
Here is what piktc preprocesses variant 2 into:
OtherMailTest init status active level notice task "this is a test" input file "/etc/hosts" rule output mail $inline if $inline =~ "loghost|localhost" if ! #defined ( #isopenOTHERMAIL ) set #isopenOTHERMAIL = #false ( ) fi if ! #isopenOTHERMAIL if #popen ( OTHERMAIL , "/usr/bin/mailx -s 'test' robert.osterlund\" , "w" ) != #err ( ) set #isopenOTHERMAIL = #true ( ) else output mail "\#popen() failure for: /usr/bin/mailx -s 'test' robert.osterlund\" quit fi fi do #write ( OTHERMAIL , $inline ) endif
The goal here was to write a one-liner macro that you can use without having to include separate begin and end script sections.
Each time we have a line match, we check to see if our open variable is defined:
if ! #defined(#isopen(F)) set #isopen(F) = #false() fi
'#isopen(F) looks like a function call, but it's not. The '(F)' is how we specify the 'F' macro parameter in the macro definition. Since the 'F' argument in the example macro reference is 'OTHERMAIL', the above macro code gets expanded to
if ! #defined( #isopenOTHERMAIL ) set #isopenOTHERMAIL = #false ( ) fi
The first and only time we call #define(), this will generate a WARNING message in the alert log:
Feb 29 13:56:56 WARNING: in exprinput(), OtherMailTest, attempt to reference nonexistent value for var isopenOTHERMAIL (1)
This is harmless. (If this bothers you, you would have to include a separate begin section where you initialize the #isopenOTHERMAIL variable, like what's done in script variant 1.)
Wait a minute? Where's the #pclose() at the end of the variant 2 script? It's not in the =output_other_mail macro definition either.
It's a little known fact that pikt closes all still open filehandles at the end of every script. Ordinarily it's good programming practice to call #fclose() and #pclose() explicitly. But in this case, in order that we can have a convenient one-liner macro and not be forced to have a separate end section to do the #pclose(), we let pikt close the filehandle for us.
There are of course other ways we could solve this problem of special email routing.
I might place on the todo list adding a new 'output mail' variant,
output mail "<addressee(s)>" "<text>"
But as you see, you don't have to wait for me to code that into the pikt script interpreter. You can achieve the same effect using the =output_other_mail macro immediately.
The =output_other_mail macro is the sort of thing that, after further polishing, could be a candidate for inclusion in the PIKT standard config library. We want to build up a large collection of macros, scripts, data sets, etc., so that you don't have to reinvent the wheel.
For more examples, see Developer's Notes.