PIKT Logo PIKT

Introduction: Reporting/Fixing a Problem

PIKT Tip Jar
PIKT is user-supported software. 
Please show your support.
 
Home
News
Introduction
Samples
Tutorial
Reference
Software
Authors
Licensing



Forum
Marketplace
Links
SiteSearch
FAQ
Contribute
Donate
ContactUs



Google
Web pikt.org


Reporting and Fixing a Problem

Oftentimes in a Pikt script, you will both report and fix problems.

For example, ClearTmpNotice is a typical Pikt script to clear tmp directories--dispose of old files and garbage files in /tmp, /var/tmp, /usr/tmp, and other temporary directories.

	ClearTmp

	        init
	                status active
	                level notice
	                task "Clear the tmp directories of garbage files"
	                input proc "=apls =dirs_tmp_obj"
	                filter "=grep -v '^l'"          // filter out links
	                =lldata

	        rule
	                set #fa = #fileage($mon,$date,$time)

	        rule    // skip these files/directories
	                if $name =~ "^/tmp/(ups_data|screens|lost\\+found)"
	                        // =execwait "=touch $name"
	                        next
	                endif

	        rule    // remove junk files 2 days old or older
	                if $name =~ "^/tmp/(crout|tty\\.txt|xntp[0-9]|
	                                    \\.X11-unix|\\.X11-pipe|
	                                    junk[0-9]*|\\.printd\\.lock|)"
	                        if (#fa > 2)
	                                =execwait "=rm -rf $name"
	                        endif
	                        next
	                endif

	        rule    // remove all non-root stuff 7 days old or older, or
	                // all stuff in, for example, /var/tmp, /usr/tmp, ...
	                if    #fa >= 7
	                   && (($owner ne "root") || ($name !~ "^/tmp/"))
	                        =execwait "=rm -rf $name"
	                        next
	                fi

	#if ! ( sheffield | berlin )
	        rule    // report all root stuff older than 15 days
	                if    #fa > 15
	                   && $owner eq "root"
                                if #fa % 7 == 0 // report only every 7 days
                                        output mail "orphaned?: $inline"
                                endif
	                endif
	#endif
	
"=apls" resolves to "/pikt/lib/programs/apls.pl," a Perl script that gives an "ls -l" listing with absolute file paths.  (apls.pl is nothing special, so we won't display it here.)  "=dirs_tmp_obj" resolves to "/pikt/lib/objects/DirsTmp.obj," a list of tmp directories we want to check, for example
        /tmp
        /var/tmp
        /usr/tmp
	...
	
Before processing the input, we pass it through the filter "=grep -v '^l'".  Note that we could have merged the filter with the proc (and eliminated the separate filter statement) by means of a Unix pipe:
        input proc "=apls =dirs_tmp_obj | =grep -v '^l'"
	
(There is good reason sometimes to have a separate filter statement, for example, when using "input file <file>" or "input logfile <logfile>".)

The proc-filter combo yields input like so:

	-rw-rw-rw-   1 vivaldi  wheel          5 Jul  7 08:40 /tmp/.700.19
	drwxrwsrwx   2 root     wheel        512 Jul  3 13:08 /tmp/.X11-unix
	-rw-------   1 root     wheel      32869 Jun 16 10:23 /tmp/junk
	drwxr-xr-x   2 root     wheel       8192 Aug 25  1995 /tmp/lost+found
	-rwx------   1 santucci perf      299893 Jul  7 10:24 /tmp/mbox.santucci
	drwxrwxrwx   2 root     other        512 Jul  2 06:22 /tmp/screens
	-rw-------   1 santucci perf         365 Jul  7 11:35 /tmp/snd.15422
	-rw-rw-rw-   1 lp       lp             0 Jul  7 11:07 /var/tmp/jadump
	-rw-rw-rw-   1 lp       lp           183 Jul  6 09:45 /var/tmp/jalog.6759
	
The data variables are mapped to the input data by the =lldata macro (defined in macros.cfg):
	lldata
	        dat    $access         1
	        dat    #links          2
	        dat    $owner          3
	        dat    $group          4
	        dat    #size           5
	        dat    $mon            6
	        dat    $date           7
	        dat    $time           8
	        dat    $name           9
	
You might choose to use this macro again and again in Pikt scripts.  It saves a lot of keystrokes and helps keep a number of Pikt scripts as concise as possible.  (Remember:  macros appear in the piktmaster source .cfg files; their resolutions appear in the slave system target .alt, .obj, or program files.  The ClearTmp script shown here is in its source version.)

Here's something new:  variable data typing.  $access is a string variable, while #links is a numerical variable.  In Pikt, variables--and functions!-- are strongly data typed.  This can be a bit jarring at first, but one gets used to it.

As we enter the input loop, we set a variable, #fa, to the fileage (in days) of the current file.  #fileage() is just one of dozens of built-in functions for your programming convenience.

In the second rule, we bypass some standard files and directories.

The next rule tests whether to delete various garbage files two days old or older.  First, we test if the current file name pattern matches the rather complicated regular expression shown.  If it does, we then test to see if the file is at least two days old.  If it is, we do an rm of that file--maybe.

Why maybe?  The action statement is

	                                =execwait "=rm -rf $name"
	
=execwait is a macro defined (in macros.cfg) as:
	#ifdef doexec
	execwait	exec wait
	#elsedef
	execwait	output mail
	#endifdef
	
doexec is a so-called PIKT "define", a logical switch we use to include or exclude sections of scripts, programs, and object files.  Defines are set in the defines.cfg file, with #define statements in other config files, or through the +D (or -D, for #undefine) command-line option.

In this case, we might be trying out this cleanup script for the first time and have therefore set doexec to FALSE.  In this case, =doexec is effectively defined as

	execwait	output mail
	
the action statement resolves to
	                                output mail "/bin/rm -rf $name"
	
on the slave system, and PIKT would send us a message of intent only.  When we are confident of this script's correctness, we could set doexec to TRUE.  After reinstalling the script on the slave, the action statement would then resolve to
	                                exec wait "/bin/rm -rf $name"
	
By this macro trick, we avoid having to use the longer construct
	#ifdef doexec
	                                exec wait "/bin/rm -rf $name"
	#elsedef
	                                output mail "/bin/rm -rf $name"
	#endifdef
	
again and again in our code.

Combined with the #ifdef-#elsedef-#endif preprocessor directives, logical defines (for example, doexec, debug, test, secure, and so on) have widespread and varied uses.  Together with the #if directive (see below), they help give you a finely grained control over your code.

Returning to the script, whether or not the file is at least two days old, we are done with it and continue on to the next.

Note the nested if-endif's.  For maneuvering around the input and rule sets, Pikt has a complete lineup of flow-control keywords, including:  if-elif-else-endif, while, for, repeat-until, switch, break, continue, again, leave, redo, next, skip, last, quit, and die.

The next rule deletes all non-root files, and all files in /var/tmp, etc., seven days old or older.  PIKT logs (in this example to Notice.log, because we have added ClearTmp to the Notice alerts) any file deletions (indeed, any actions that might impact on the external environment).

The last rule considers all other files:  root-owned files in /tmp.  If any of these are at least 15 days old, we send e-mail indicating that.  Note how, by using the "#fa % 7" test, we restrict this warning e-mail to just once (per file) per seven days.  We don't want to be buried in a blizzard of unimportant reminder alerts, so using tricks like this one is common.

Note, too, that by means of the #if directive, we filter out the last rule from the target ClearTmp script on two machines, where long-standing /tmp files are commonplace.  The last rule would appear in the preprocessed target on every other machine aside from the two listed.

Similar to #ifdef, the #if-#else-#endif preprocessor directives have PIKT include or exclude script (and other) statements at the per-machine or per-operating system layer.  #if directives are governed by the hosts and operating systems you specify in the piktmaster's system.cfg file.

For the ClearTmp script, here is a sample e-mail alert:

	                               PIKT ALERT
	                        Tue Jul 15 09:51:50 2003
	                                 antwerp

	NOTICE:
	    ClearTmp
	        Clear the tmp directories of garbage files

	        orphaned?: -rw-rw-rw- 1 root daemon 1234 Jun 28 08:26 /tmp/auth.log
	        orphaned?: -rw-r--r-- 1 root daemon 7336 Jun 28 08:26 /tmp/fstab.orig
	
You might have noticed something odd about the nested if-endifs in the third rule above.  In the inner if-endif, the condition is enclosed in parentheses, while the condition for the outer if-endif is not.  In Pikt, parentheses around if-endif conditions, as well as parentheses in while, repeat-until, for and switch statements are optional.  No pesky semicolons to worry about either!

And that's not all.  Did you catch the "fi" in the fourth rule?  For many keywords, you may choose among several synonymous alternatives.  If you program using many different languages like we do, how many times have you used "elif" instead of "elsif" or "elseif," and your program failed for that (aggravatingly stupid) reason?  In Pikt, elif, elsif, and elseif are all legal, and all have the same effect!



Home | News | Introduction | Samples | Tutorial | Reference | Software | Authors | Licensing
Forum | Marketplace | Links | SiteSearch | FAQ | Contribute | Donate | ContactUs
Top of Page

Join pikt-users, pikt-workers, and/or the PIKT Forum. 
Open Hand Please visit our sponsors.

Page best viewed at 1024x768.   Page last updated 2005-01-09.
This site is PIKT® powered.
PIKT® is a registered trademark of the University of Chicago.
Copyright © 1998-2005 Robert Osterlund.  All rights reserved.