Statements
(NOTE: Some of the techniques shown or described on this page--marked in purple--require new features in the latest official PIKT 1.19.0 release (pikt-current.tar.gz) that are unavailable in any previous version.)
In Pikt scripts (and excepting the script/stanza name, in the leftmost column), every statement begins with a statement keyword. Most you have seen already:
KEYWORD ATTRIBUTE init begin rule end status active|inactive level emergency|alert|critical|error| warning|notice|info|debug task "Here are the rest of the statement keywords:" input proc|process " " file " " logfile " " filter " " seps|separators " " dat|data keys [ ...] if else elif|elsif|elseif endif|fi while endwhile repeat until for in endfor foreach endforeach break continue|cont switch case default breakswitch|breaksw endswitch|endsw again leave redo next skip last pause quit die " "
KEYWORD ATTRIBUTE do'do' is akin to a nullop. For example, you might use 'do' this way:set = unset|delete exec [wait] " " doexec [wait] " " output [mail ""] [print " "] [" "|piktlog|syslog " "]
do #split($command("=lld (F)")) set #fa = #fileage($[6],$[7],$[8])The '=lld' macro typically resolves to "/usr/bin/ls -ld", which reliably gives a so-called "long listing" of files or directories. You might check the return value of the #split() command, as in
if #split($command("=lld (F)")) == 9 set #fa = #fileage($[6],$[7],$[8]) else output mail "bad result from: =lld (F)" quit fibut that would be overkill. Simply doing
#split($command("=lld (F)"))would result in a syntax error, because every Pikt script statement must begin with a keyword (#split() is a function, not a keyword).
You might try assigning the #split() result to some arbitrary, throw-away variable
set #dontcare = #split($command("=lld (F)"))but that's a somewhat stupid kludge. Better to use 'do'.
So, use 'do' when when you want to make a function call for its side effects (e.g., when opening a file with #fopen(), as in 'do #fopen($fil)) and you don't care about the return value (but maybe you should!).
'set' is for assigning values (either string or numerical expressions) to variables. For example,
set #period = 24*60And another example,
set $pagemsg = "$sys is down!"Performing a set on a dat variable is illegal (input data assigned to dat variables cannot be overridden). Illegal, too, is performing a set on a filehandle (e.g., FOO), preceding variable (e.g., ), and previous variable (e.g., %foo); once assigned (in the preceding/previous case by Pikt itself internally), these values may not be changed. An exception is a file handle opened then closed; it may then be reassigned to with a subsequent open function.
A special form of the set action appears in a for statement. For example,
for #i=0 #i<10 #i+=1The '#i=0' and '#i+=1' are implied set actions, but in this context the set keyword is neither necessary nor allowed. To repeat: parentheses, however, are. This is legal:
for (#i=0 #i<10 #i+=1)Use whatever form you're comfortable with (although using parentheses can, in unusual circumstances, be problematic; it's best not to use them).
The 'unset' keyword (aka 'delete') removes an element from an associative array, for example:
unset $shell["daemon"]or, equivalently:
delete $shell["daemon"]'exec' is for executing a command string when you don't care about the return value (otherwise you could use 'do #system()' or 'do $command()'). 'exec wait' temporarily halts the script run until the exec'ed command finishes. You would normally use exec wait, resorting to just plain exec for unusually time-consuming exec'ed commands.
'doexec' is akin to the doexec define.
When a script is in testing status, script 'exec' and 'exec wait' statements become effectively 'output' (or 'output mail'), and command strings are reported and/or logged rather than executed. But consider the following situation:
dmesg_scan(BYPASSES) init status =piktstatus level =piktlevel task "Scan the dmesg output for troublesome or noteworthy entries" input proc "if [ -e =hstdir/log/dmesg=piktalert=_.bak ]; then =diff =hstdir/log/dmesg=piktalert=_.bak =hstdir/log/dmesg=piktalert | =egrep '>' | =cut -b 3- 2>/dev/null; else =cat =hstdir/log/dmesg=piktalert 2>/dev/null; fi" begin exec wait "=dmesg | =uniq > =hstdir/log/dmesg=piktalert" rule [... input processing follows ...]In the 'begin' section 'exec' statement, the intent is to send dmesg output to a file, which is then used as script input in the 'input proc' statement. In testing mode, the 'exec' would in fact not execute, there would be no saved dmesg output, and the script would be rendered useless.
To fix this, you would use the 'doexec' (or 'doexec wait') statement to force command execution in all cases. If instead you where to have
doexec wait "=dmesg | =uniq > =hstdir/log/dmesg=piktalert"the dmesg output would be written to the file whether or not the script is in testing mode.
So, use 'doexec' where essential to the script operation and ordinary 'exec' where the indicated command execution is optional (or for safety's sake during the script development and testing phase you want a command to be reported rather than executed).
The 'output' statement is akin to other language's 'print'. For example,
output mail $inlinor
#ifdef debug rule output "$text(#cpu,1) $text(#mem,1) $prc" #endifdefWhen used as
output "the text string is sent to the user screen (stdout). Usually, output is sent as e-mail using the statement"
output mail "If you run a Pikt script interactively from the command line, for example,"
# pikt +A Urgent'output mail' works effectively as plain 'output'. So, when developing and testing a new Pikt script, where you run the script interactively during the development and debugging process, there is no need to change your 'output mail' statements to 'output'. In either case, output will be sent to stdout.
Print output, or output to a logfile, is achieved by inserting the keyword 'print', or the appropriate log keyword after the 'output'. 'output piktlog' outputs to the current alert's log file (e.g., Urgent.log), 'output syslog' logs to the system log (syslog), and 'output log "
Note that the logfile can be a computable string, as in
output log "=logdir/" . $alarm() . ".log" $inlin
In Pikt, you achieve the functionality of other language's printf() by means of the string formatting functions.
When run non-interactively (i.e., when called without human intervention by piktd), or when run at the command line but with either the +M or +L options, pikt queues mail and print message lines until the end of its program run, only sending out e-mail or dumping to a printer just before pikt terminates. In 'log' statements, on the other hand, the message line is logged to the current alert log, to syslog, or the special log file immediately.
There are no practical limits to the number of Pikt script statements, nor to the number of rules. There can be only one init, begin and end section, though.
Refer to the sample alarms.cfg for many more examples.
prev page | 1st page | next page |