Fixing a Problem
Besides reporting problems, you can also configure PIKT to fix them.
For example, KillIdleUserSession is a short Pikt script to automatically kill idle user sessions--inactive user logins. Here is the script as it would appear in its source version on the piktmaster system (in the alarms.cfg file):
KillIdleUserSession init status active level critical task "Terminate idle user sessions" input proc "=w | =awk '/[1-9]days/ {gsub("/","\\\\/"); print $1 " " $2}'" dat $user 1 dat $tty 2 rule exec wait "=kill -9 `=ps -aux | =awk '/$user.+$tty/ {print \$2}'`"
Note the '=' as in '=w', '=awk', and so on. The '=' signifies a PIKT macro. In the piktmaster's macros.cfg file, we might specify these macros this way:
#if linux ... w /usr/bin/w awk /bin/gawk ps /bin/ps kill /bin/kill ... #elsif solaris ... w /usr/bin/w awk /usr/bin/nawk ps /usr/bin/ps kill /usr/bin/kill ... #elsif freebsd ... w /usr/bin/w awk /usr/bin/awk ps /bin/ps kill /bin/kill ... #endifSuppose again that we have added the KillIdleUserSession script to the Critical alerts group. On the piktmaster system, we would issue the command to install the Critical scripts, including the KillIdleUserSession script, on calais2:
# piktc -iv +A Critical +H calais2(Since we scheduled and enabled the Critical script group earlier by means of the '-e' (enable) and '-r' (restart the piktd daemon) options, there is no need to repeat them here.)
Here is the final, preprocessed script version as it would be installed in the Critical.alt file on the calais2 (Linux) slave system:
KillIdleUserSession init status active level critical task "Terminate idle user sessions" input proc "/usr/bin/w | /bin/gawk '/[1-9]days/ {gsub("/","\\\\/"); print $1 " " $2}'" dat $user 1 dat $tty 2 rule exec wait "/bin/kill -9 `/bin/ps -aux | /bin/gawk '/$user.+$tty/ {print \$2}'`"Note how, after preprocessing and macro substitution, full command paths have been inserted for the w, awk, ps and kill commands. If this were for a Solaris, FreeBSD, or other system, different paths would be inserted (for example: /usr/bin/w, /usr/bin/nawk, /usr/bin/ps and /usr/bin/kill, for Solaris; /usr/bin/w, /usr/bin/awk, /bin/ps and /bin/kill, for FreeBSD; etc.).
Reflect for a moment on what this means. Through the magic of PIKT macros and configuration file preprocessing, this identical source script should work across all operating systems. You no longer have to concern yourself with specifying the correct path for this or that command in your scripts, either by maintaining separate script versions or by inserting per-OS case statements into your code. Simply define the path once and for all (in the macros.cfg file), then use the =awk macro (for example) ever after in all of your scripts. PIKT will automatically install and use the appropriate version.
Note that we just wrote "all of your scripts." This includes scripts written in other languages (such as Perl, Awk, Python, etc.) that you maintain by way of PIKT (in your programs.cfg file).
Returning to the KillIdleUserSession script, the script gets its input data from the command "=w", which on this system preprocesses to "/usr/bin/w". Here is some sample input:
8:10am up 7 day(s), 16:22, 3 users, load average: 0.46, 0.48, 0.49 USER TTY LOGIN@ IDLE JCPU PCPU WHAT root pts/0 Mon 7am 48 44 /bin/bash bach pts/2 29Jun98 3days /usr/local/bin/zsh root pts/3 Mon 7am 2 1:55 19 /bin/bash bach pts/4 29Jun98 3days 3:25 2 /usr/local/bin/zsh bach pts/6 29Jun98 2days /usr/local/bin/zsh liszt pts/8 2:58pm 15:34 slogin vienna root pts/9 8:07am 3 wWe pass this input along to awk with the instructions:
- match lines showing idle time in days
- transform, for example, "pts/2" into "pts\/2" (needed because we are passing the tty to another awk command below, and without the added backslash escape the subsequent awk command would fail; the multiple backslash escapes are explained in the PIKT Reference)
- output just the first and second fields
Here is the resulting awk output:
bach pts\/2 bach pts\/4 bach pts\/6A data variable, $user, of string type, matches the first field. (Field delimiters default to whitespace.) $tty is the second field. $user and $tty are assigned anew with each input line.
This alarm has but one rule. A rule is a collection of program statements, usually to consider just one condition. In this simple example, there is no conditionality. We exec a kill command to terminate the idle session in question. (The exec is automatically logged for auditing/debugging purposes.)
We get the pid for the kill using a little Unix command-line magic. If you're not an Awk aficionado, at this point you might be a bit concerned. Not to worry, you don't need to know any Awk in order to use PIKT. Knowledge of Awk, Perl, Python, or the shell scripting languages comes in handy, especially when formulating Pikt input statements, but knowing these other languages is not essential. In your scripts, whether you use just the Pikt language, one or more of the other languages, or a combination of languages is entirely up to you.
You could, if you want, add rules to:
- kill root sessions only
- kill on certain systems only
- kill after midnight and/or on weekends only
- kill only if certain other conditions are met
- send e-mail alerts to the system operators, who could then decide if manual session kills are required
... // note that, in addition to any special logging below, by default // all kills are logged in the alert log file in the usual fashion rule // set the kill command set $killcmd = "\=kill -9 `\=ps -aux | \=awk '/$user.+$tty/ {print \$2}'`" #ifdef debug // just show the $killcmd, but don't exec it output $killcmd next #endifdef #ifdef paranoid rule // always kill if paranoid exec wait $killcmd // log to syslog output syslog "idle session: $inlin" // and also do special logging =output_alarm_log($inlin) next #endifdef // paranoid #if server rule // tolerate idle root & sysadmin sessions on server systems if $user eq "root" || $user =~ "=sysadmins" // for now, let's not kill, just report output mail "idle session: $inlin" // exec wait $killcmd else // shouldn't have other users on server // systems anyway, so always kill (and report) output mail "killing idle session: $inlin" exec wait $killcmd fi next #endif // server // user systems only after this point #if sysadmin rule // on sysadmin systems, just silently ignore quit #endif rule // no moonlighters allowed if =latenight || =earlymorning || =weekend exec wait $killcmd fiThis is a rather elaborate example, of course. Simplify or complicate your own rule sets as needed.
prev page | 1st page | next page |