[Treachery Unlimited Logo] Treachery Unlimited: A Computer & Network Security Information Clearinghouse Site

Advisory Agencies
Articles and Tutorials
Security Tools
Site Search
Feedback to Webmaster
LoadMon: Web Server Graphical Load Indicator
by Jay D. Dyson <jdyson@treachery.net>

FOREWORD:

I have been approached several times regarding the "Current Load" indicator that's displayed at the bottom left-hand side of the main page of Treachery Unlimited. In the time that this load display has been up, I've received a number of inquiries which boil down to two basic questions:

  • Is that a real system load indicator, or is it just a mock-up?
  • Will you release the source code?

In answer to these questions: yes, it is a real load indicator; and yes, I will release the source code. In fact, the utility is really quite simple and the commenting in the PERL code makes it rather self-explanatory, so this web page is the only documentation I'll write for it.

This software is released under the terms and conditions of the Gnu Public License (GPL). I wrote it, and I'd appreciate credit for it. That's all.

DOWNLOADING THIS SCRIPT:

 [>  loadmon-1.2.tar.gz
  SHA1 Hash:  c4cdb3c925d3d2029274c616acdfea44a4601fd6
   MD5 Hash:  4542cebb6b3924db889cdea51dca5f07

PURPOSE OF THIS SCRIPT:

This script was authored as a remote diagnostic tool to rule out system resource starvation in the event of slow web server response. By ruling out system load as a factor, I was able to focus my investigation on network conditions which could account for any server response lag. This was particularly useful when I was in a location or situation in which I could not securely log in to the web server in question.

Side note: While the images associated with this script will need to be placed somewhere in the document root of your web server, this script can be installed anywhere on your system.

ROLE OF THIS SCRIPT:

This script is not a CGI script! This script is a continually-running program that is initiated by the user (or via system startup scripts) and runs in the background. What this script does is generate HTMLized output at defined intervals set in the script itself. The HTMLized output file can then be incorporated into a selected web page (or pages) using the Server Side Include "include file" directive.

This script was designed with UNIX systems in mind. Since Microsoft Windows does not have a native equivalent to UNIX uptime(1), it's unlikely this script can ever be adapted for any PERL variant used on Windows. But hey, things change. Maybe someday...

THE SCRIPT, WITH COMMENTARY:

The script opens with all the standard comments, but take special notice to the requirements listed here (PERL version, SSI enabled on the web server, and images). If you are unfamiliar with how to enable Server-Side Includes (SSI) on your web server, consult your web server's documentation.

Depending on your OS, PERL may be located somewhere other than /usr/local/bin.   Do a 'which perl' at the command line to determine PERL's location on your system and modify this script accordingly.

  #!/usr/local/bin/perl -T
  #
  # LOADMON  : Graphical system load display for web pages.
  # AUTHOR   : Jay D. Dyson <jdyson@treachery.net>
  # VERSION  : 1.2 (Released to public - 09/08/2002)
  # REQUIRES : PERL v5.x or higher; Server-Side Includes
  #            enabled on web server; nohup execution (or
  #            inclusion in system startup scripts); and 4
  #            images (provided with distro tarball).
  # LICENSING: Released under GNU Public License (GPL).
  #

First you must define the path and filename where the script can write the parsed uptime report. You will need to change this path declaration to match the directory used by your own system. The destination file and directory must be user-writable, so whoever runs this script will need to have the appropriate write access permissions.

  $on="/PATH/TO/WEBDIR/LAST_LOAD_FILENAME";

Next is the destination where the script writes the HTMLized output that is the graphical load display. Like the previous directory and file, this must be writable by the user and must be readable by the web server (e.g., be in the web server's document directory).

  $fn="/PATH/TO/WEBDIR/HTML_OUTPUT_FILENAME";.

The following code is comprised of defined HTML and image values. These are the building-blocks for the HTML output of the load monitor script. Also of note is the clearing of the $PATH environment variable. This is done to comply with the PERL taint mode (which enhances script security).

  $ENV{'PATH'}="";$i1="<img src=\"";
  $i2="\" height=10 width=8 alt=\""; 
  $i3="\:\">"; $i4=".\">";
  $i5="$i1"."green_on.jpg"."$i2$i3"; 
  $i6="$i1"."red_on.jpg"."$i2$i3";
  $i7="$i1"."greenoff.jpg"."$i2$i4"; 
  $i8="$i1"."redoff.jpg"."$i2$i4";

Next is the beginning of the load calculations and graphical representation output assembly.

First we start with an endless loop condition.

  while (true) {

Keep in mind that, once this script starts, it will run until it is killed. If you start this script via an interactive shell, it will be killed if you should logout or hit Ctrl+C. Thus, you will need to start this script using either nohup(1) like this:

nohup ./loadmon > /dev/null 2>&1 &

...or you'll want to add it to a system start-up script. With Linux and most BSD variants, this would be /etc/rc.d/rc.local. With Solaris, you can create a start up script that would be something like /etc/rc2.d/S99loadmon. The contents of your startup script would be similar to the above command line invocation, only you will need to declare the path to the loadmon script.

The following line resets the "light" counter and sets the first "light" at on (since a completely unlit string of lights would indicate no system activity, which would be untrue). This line also defines the location of the uptime binary. If this resides somewhere other than /usr/bin on your system, you will need to change this value.

  $n=0;$ld="$i5";$a=`/usr/bin/uptime`;

This next line parses the output from uptime and extracts the load average value we'll use for the load indicator. Scalar variable reassignments are performed for the purpose of arithmetic decrements on the load value while preserving the original load number.

  $a=~s/(.*)average:\s+//ig;$a=~s/\s+//g;
  @b=split(/,/,$a);$l=$b[1];$m=$l;

At this time, a file handle is assigned to open and read the load value information previously written to the "last load" report file.

  open(L,"<$on");while(<L>){chomp($_);$o=$_;}close(L);

Before proceeding further, the script checks to see if the load has changed since it last wrote to the "last load" file. If the load value has not changed, there is no need to re-generate the HTML and the script will go back to sleep. If the load value has changed, then the script will proceed with new HTML output generation.

  if($l!=$o){

The following lines step through the output and decrement the load value data by ten percent (via the subroutine named 'id') with each pass. A total of 10 rounds occur, since 10 times 10% equals 100% and the graphical load indicator has 10 "lights."

Following each 10 percent decrement, each resulting positive value is assigned an 'on' image filename which is appended to the constructed HTML that will be written to the HTML output file. When the value reaches zero or becomes negative, the 'off' image filename is assigned. When the image assignments are complete, the value of the original load is assigned a "human" named value so visitors using text-based browsers (such as Lynx and Links) will also know the current load status.

  while($n<6){if($m>0.10){$ld="$ld"."$i5";}
       else{$ld="$ld"."$i7";}&id;} # Green images
  while($n<9){if($m>0.10){$ld="$ld"."$i6";}
       else{$ld="$ld"."$i8";}&id;} # Red images
  if($l>0.70){$lv="High";}
       elsif(($l<0.71)&&($l>0.29)){
       $lv="Moderate";}else{$lv="Nominal";}

After the entire HTML conversion is completed, the "HTML output" file is written to. File locks are performed briefly so that any simultaneous web requests will pause for a fraction of a second while the new load information is written. This prevents incomplete HTML rendering which can skew the visitor's web page appearance. There is no appreciable lag for the end user since the open, lock, write, and unlock event occurs within an imperceptible period of time.

  open(O,">$fn");flock(O,2);
      print O "$ld<br><font size=1>($lv)<font>\n";
  flock(O,8);close(O);

Once the calculations are complete and the new HTML output has been written, the script closes the process by updating the numeric load value to the "last load" file.

  open(M,">$on");print M "$l\n";close(M);

Once all of the above steps have completed, the script sleeps for 60 seconds. You can change this value to suit your preferences, though it is not recommended that you set the sleep time to less than 30 seconds as this will not yield any appreciable quality in load reporting.

  } sleep 60;

This is the previously-mentioned calculation subroutine. This exists to avoid redundant code.

  } sub id {$m=$m-0.10;$n++;}

CLOSING REMARKS:

That's the graphical load monitor script in a nutshell. Please drop me a line if you find this script useful.


Copyright © 1999 - 2011 • Treachery Unlimited.
Last updated on Sunday, 11-Apr-2004 01:48:47 MST Privacy Policy