<SECTION>Introduction</SECTION>

Hello and welcome to the OmniMoni demonstration.  This Tcl/Tk Demonstration script is very simple, and lacks almost any error checking or robustness.  It's purpose is to allow you to read through the demonstration explanations and easily try out the OmniMoni demonstration scripts.  Having said that, on to OmniMoni.

This demo is, in part, a tutorial.  Each demo has a brief explanation and shows the OmniMoni configuration file.  If you are just checking out OmniMoni then you don't have to read any of that stuff and you can just click (with the left mouse button) on the highlighted areas to see those demos.

If you would like to learn how to create your own configuration files, or how to alter these ones, then this tutorial should be used along with the OmniMoni man page.  It gives complete details on how to do everything in the configuration files.  Although I try to demonstrate each piece here, the best source is the man page.

All of the examples in this Demonstration depend on the usage and output format of the command being executed as being consistent.  As you move from one operating system to another, commands have different flags and different output.  This was written on a BSD (mostly) system, Linux.  If a particular command does not run, or does not exist, you will see an error message appear in shell window from which the Demonstration was run.  If this happens you can retry that command by clicking on it with the middle mouse button to see it as a static command, or you can go on to the next example.  If you know that the command will not run, you can select that demo with the middle mouse button to begin with.  This will run OmniMoni in debug level 4 mode (see the man page) which will still show the layout of the demonstration, but all of the fields will be static, hence the command is never run.

With all OmniMoni displays, you can click on any dynamic label with the left mouse button to "demand" an update.  This is most useful for those items that only update rarely.  This generally takes one to two seconds to occur depending on machine speed.

To quit a running OmniMoni type "Q" (capital "q") while the mouse is in the OmniMoni window.

To quit this demo/tutorial, type "Q" while the mouse in the the demo window.

If you've created any configuration files you think would like to share, please e-mail them to me at rvm@fore.com.  I am especially looking for general, useful, simple scripts for non-Linux operating systems.  Examples are memory, diskspace, load monitors, etc.


				Thank you,

				Rainer Mager



<SECTION>1:  whoami.omnirc</SECTION>

Ok, since we're just starting out I will be painfully simple.  This shows who you are.  Type "Q" (capital "q") while the mouse pointer is in the window to stop OmniMoni, and go to the next demonstration.

The format for the configuration file is a relatively simple, recursive one.  The idea is that you have a command, and somewhere in that command, you also have zero or more other commands (recursively).  There are four different possible commands in this version of OmniMoni.  They are:  configure, group, graph, and comment.  Group and graph will most likely be the most common ones, and of the two, group is the most simple.  So, here is your first OmniMoni configuration file with only group commands.

<FX>{   group Command {} {"whoami"} 10 left {}
<FX>    {   group me {"$0" left {}}}
<FX>}

This creates a group called "Command", it has no label "{}", the command being run is "whoami", it's children are updated every "10" seconds, it is packed to the "left", and there are no extra parameters for it's children "{}".

"Command" has one child, "me".  It has a dynamic label "$0" which means take field "0" of the output from its parent's command, "whoami".  It is packed to the left and has no extra parameters, or further options.  Actually "me" takes the same parameters as "Command" (and any group), but the end ones are just left as null.  The only reason this is ok is because as soon as OmniMoni sees that "me" has no children, it completely ignores those later parameters.

Note that the whole thing is enclosed in curly braces, "{}".  These braces are actually part of the first group command, "Command".  For complete details on any of the commands see the man page.

To see this demo, <DEMO-IT>demos/whoami.omnirc</DEMO-IT>, click on it.



<SECTION>2:  loadavg.omnirc</SECTION>

This one's still pretty simple, but now we're looking at multiple fields and we're looking at them from the right.  OmniMoni can pull fields out of the program's output from the left to the right and from the top to the bottom (the way English is read), or the opposite way.  Also, in this one, we add a static label.

<FX>{   group Command {"Load Average" top {}} {"uptime"} 10 left {}
<FX>    {   group T-1 {"%2" left {}}}
<FX>    {   group T-5 {"%1" left {}}}
<FX>    {   group T-15 {"%0" left {}}}
<FX>}

The group "Command" has a static label "Load Average" to the "top" of the children, and with no extra parameters "{}".  Its command to run is "uptime", its children are updated every "10" seconds, and they are packed to the "left" with no extra parameters "{}".

These children use the "%" syntax, which mean pull the fields in the opposite order.  The reason the children are horizontal is because "Command" has them set to "left" (in the "10 left {}" part).  The "left" in the children themselves defines where their label "%n" is in relation to their children, of which there are none.  So changing the direction in the children would have no affect, in this example.

On my system, the command "uptime" return output in the form:

<FX>11:25am  up 16:34,  2 users,  load average: 1.27, 1.18, 1.11

But, it will also sometimes return output in the form:

<FX>11:25am  up 2 days,  2 users,  load average: 1.27, 1.18, 1.11

For the second one, there is 1 more field from left to right.  That is why I pull the fields out from right to left.  I am guaranteed that the first three fields, from the right, are what I want.

To see this demo, <DEMO-IT>demos/loadavg.omnirc</DEMO-IT>, click on it.



<SECTION>3:  loadavg2.omnirc</SECTION>

Now, if you were paying attention (and your OS displayed it the way mine does), you might have noticed some ugly commas in that previous one.  This one's the same as the last one, but we get rid of the commas using the split ability.  Also, we show a simple line graph. This will update every 2 seconds, so give it a bit of time to put some stuff on the graph.  If you want to see it scale the graph run a few background processes to generate load.  My favorite load creator is:

<FX>gzip -9 < /dev/zero > /dev/null

Run it in the background 10 - 20 times and the graph will change quickly.  Don't do that if your on a machine with other users, they would most certainly mind.

<FX>{   group LoadAvg {"Load Average" top {}} {"uptime"} 2 top {}
<FX>    {   group Labels {} {} 2 left {}
<FX>	{   group T-1 {"|, %2" left {}}}
<FX>	{   group T-5 {"|, %1" left {}}}
<FX>	{   group T-15 {"|, %0" left {}}}
<FX>    }
<FX>    {   graph Title {"The Graph" top {}} {} 200 80 1 white black 2 left 200 {}
<FX>	{   "T-1" "|, %2" "red" lined }
<FX>	{   "T-5" "|, %1" "green" lined }
<FX>	{   "T-15" "|, %0" "blue" lined }
<FX>    }
<FX>}

For the children of "Labels", they use the "|," symbol.  This replaces every instance of comma "," with whitespace in the output of their parent (or parent's parent in this case).  Note that it is important that the symbol "|," comes before the symbol "%n".  This is because it will first split the output, then it will take the field.

The graph "Title" has the label "The Graph", with a width "200", height "80", hash marks every "1" (in reference to numbers pulled in from the label symbols, %n), the color for the hash mark at zero is "white", all other hash marks are "black", it updates every "2" seconds, scrolls to the "left", has a history of "200", and has no extra parameters "{}".

To see this demo, <DEMO-IT>demos/loadavg2.omnirc</DEMO-IT>, click on it.



<SECTION>4:  date.omnirc</SECTION>

This one's a calendar and a clock.  The main point of this one is to show the ability to configure how often each item is updated.  So that you don't get too bored I also added a little extra configuration item via the variable substitution features.  These variable substitutions can appear anywhere in the configuration file and are substituted before anythng else is parsed.

Note that if your system load is high it may update slower than once a second.  This one depends on the output of "date" being in the form like:

<FX>Wed Feb  8 22:04:03 JST 1995

If it is not you will see output, but it won't be what I intended.

<FX>{   group Command {"The current date and time" top {"-foreground $COLOR"}} {"date"} 1 top {}
<FX>    {   group Date {} {} 1 left {}
<FX>	{   group Day {"$0" left {}}}
<FX>	{   group Month {"$1" left {}}}
<FX>	{   group Date {"$2" left {}}}
<FX>	{   group Zone {"$4" left {}}}
<FX>	{   group Year {"$5" left {}}}
<FX>    }
<FX>    {   group Time {"$3" left {}}}
<FX>}

To see this demo in blue, <DEMO-IT>demos/date.omnirc --set COLOR blue</DEMO-IT>, click on it.
To see this demo in red, <DEMO-IT>demos/date.omnirc --set COLOR red</DEMO-IT>, click on it.
To see this demo in geeen, <DEMO-IT>demos/date.omnirc --set COLOR green</DEMO-IT>, click on it.
To see this demo in blue-green, <DEMO-IT>demos/date.omnirc --set COLOR #0ff</DEMO-IT>, click on it.



<SECTION>5: users.omnirc</SECTION>

This one begins to show the flexibility possible.  It shows the number of users on the system.  But, there is no standard command that shows this (although some implementations of "uptime" will).  Also, there is a graph 24 hours wide given each pixel is plotted every 15 minutes (total of 192 pixels wide).  This can easily show you how many people were on for the past 24 hours (although since this one does update slowly it ony notices people on if they're on during the check).

<FX>{   group Command {} {"who | wc"} 10 top {}
<FX>    {   group Text {} {} 10 left {}
<FX>	{   group Pre {"There are" left {}}}
<FX>	{   group Users {"$0" left {"-foreground red"}}}
<FX>	{   group Post {"users on this machine right now." left {}}}
<FX>    }
<FX>    {   graph History {} {} 192 50 10 "" red 900 left 192 {"-bg black"}
<FX>	{   "Users" "$0" "white" solid }
<FX>    }
<FX>}

To see this demo, <DEMO-IT>demos/users.omnirc</DEMO-IT>, click on it.



<SECTION>6:  total-users.omnirc</SECTION>

This one's similar to the last but it contains a slightly more complex command and it is definitely something that no single command could give you.  It monitors the total number of users that have accounts on the system.  Say you were a commercial account provider.  You would probably only have this update once every day since it probably won't change very fast.  This of course requires that all of the users have directories in the "/home" directory.

This example also shows the ability to hide and show certain pieces of the output.  After it comes up, press the right mouse button, and select "Pre" and "Post" and see how it changes.  You can close the menu with the right mouse button.  After the new text appears, try clicking on those sections (the actual text) with the middle mouse button.  Then look at the menu again.

<FX>{   group Command {} {"ls -1 /home | wc"} 1 left {}
<FX>    {   !group Pre {"There are" left {}}}
<FX>    {   group Total {"$0" left {"-foreground red"}}}
<FX>    {   !group Post {"accounts on this machine." left {}}}
<FX>}

Notice the "!" sign precedeing the groups "Pre" and "Post".  These tell OmniMoni to configure those in, but have them initially unpacked.  If you do this to a dynamic label, while it is unpacked, it will not be updated.  This can save resources while running if you do not need that information.  I do that with my PPP statistics and only show it when I'm connected.

To see this demo, <DEMO-IT>demos/total-users.omnirc</DEMO-IT>, click on it.



<SECTION>7:  meminfo.omnirc</SECTION>

This one finally gets pretty interesting.  It show a lot more information, demonstrates some of the math abilities when parsing fields, and shows some more aesthetic options (notice the kludgy "Mem Info" label).  This example also introduces the ability to give global configuration options.  In this case the font among some other things is changed.  Unfortunately, this one will not show the correct output unless you have the command "free".  This is a standard Linux command and gives output in the form:

<FX>             total       used       free     shared    buffers
<FX>Mem:      19976192   15970304    4005888    5689344    6664192
<FX>Swap:     21069824    7905280   13164544

If you do not have the command then click on this on with the middle mouse button and you can see the format without useful information in it.

<FX>{   configure
<FX>    {*font 6x12}
<FX>    {*borderWidth 1}
<FX>    {*padX 1}
<FX>    {*padY 1}
<FX>    {*ipadX 1}
<FX>    {*ipadY 1}
<FX>}

<FX>{   group MemInfo {"M\ne\nm\n\nI\nn\nf\no" left {"-bg yellow"}} {"free -b"} 10 left {"-border 2" "-relief sunken"}
<FX>    {   group Sunken {} {} 10 left {}
<FX>	{   group Type {} {} 5 top {}
<FX>	    {   group Shared {"Shared:" top {"-fore red"}}}
<FX>	    {   group Empty1 {""        top {}}}
<FX>	    {   group Empty2 {""        top {}}}
<FX>	    {   group RAM    {"RAM:"    top {"-fore red"}}}
<FX>	    {   group Swap   {"Swap:"   top {"-fore red"}}}
<FX>	    {   group Memory {"Memory:" top {"-fore red"}}}
<FX>	}
<FX>	{   group Total {} {} 5 top {}
<FX>	    {   group Shared {"$9"       top {}}}
<FX>	    {   group Empty  {""         top {}}}
<FX>	    {   group Type   {"Total"    top {"-fore red"}}}
<FX>	    {   group RAM    {"$6"       top {}}}
<FX>	    {   group Swap   {"$12"      top {}}}
<FX>	    {   group Memory {"$6 + $12" top {}}}
<FX>	}
<FX>	{   group Used {} {} 5 top {}
<FX>	    {   group Buffers {"Buffers:" top {"-fore red"}}}
<FX>	    {   group Empty   {""         top {}}}
<FX>	    {   group Type    {"Used"     top {"-fore red"}}}
<FX>	    {   group RAM     {"$7"       top {}}}
<FX>	    {   group Swap    {"$13"      top {}}}
<FX>	    {   group Memory  {"$7 + $13" top {}}}
<FX>	}
<FX>	{   group Free {} {} 5 top {}
<FX>	    {   group Buffers {"$10"      top {}}}
<FX>	    {   group Empty   {""         top {}}}
<FX>	    {   group Count   {"Free"     top {"-fore red"}}}
<FX>	    {   group RAM     {"$8"       top {}}}
<FX>	    {   group Swap    {"$14"      top {}}}
<FX>	    {   group Memory  {"$8 + $14" top {}}}
<FX>	}
<FX>    }
<FX>}

The first part, is global configuration options.  These will effect everything created after them, unless overridden with specific parameters or changed with another configuration command.    They are all Tcl/Tk options for the Tk options database.  Unfortunately, I can not give complete details on all of the options here.  I recommend reading the Tcl/Tk manpage on "options".

Besides that, the only new thing here is the math operation in the last child of the "Total", "Used", and "Free" groups.  All it does, is take the numbers from the fields as described by the special symbols, and after it has all those numbers, it tries to perform the given math operation on them.  If this results in a number, then that's the answer.  If it does not (which could happen if one of the fields returns a non-number), then it uses the actual string given (the same as if you were in debug level 4).  Complex math operations are allowed, using any of the Tcl math functions, the only criteria is that any special symbols are white space delimited on both sides.


To see this demo, <DEMO-IT>demos/meminfo.omnirc</DEMO-IT>, click on it.



<SECTION>8:  meminfo2.omnirc</SECTION>

This one shows the same information as the previous, except that it does it with a graph.  Actually, it doesn't quite show all the information of the previous, but you'll see.

<FX>{   group MemInfo {"M\ne\nm\n\nI\nn\nf\no" left {"-fg yellow" {-bg "dark red"}}} {"free -b"} 1 top {}
<FX>    {   group Key {} {} 10 left {"-bg black"}
<FX>	{   group RAM {"RAM" left {"-fore #0f0"}}}
<FX>	{   group Swap {"Swap" left {"-fore #33f"}}}
<FX>	{   group Memory {"Memory" left {"-fore #f00"}}}
<FX>	{   group Used {"Used" left {"-fore #fff"}}}
<FX>	{   group Free {"Free" left {"-bg #fff" "-fore black"}}}
<FX>    }
<FX>    {   graph Meminfo {} {} 300 100 5120000  "" white 1 left 600 {"-bg black"}
<FX>	{   U-RAM     "$7"       #0f0 lined }
<FX>	{   U-Swap    "$13"      #00f lined }
<FX>	{   U-Memory  "$7 + $13" #f00 lined }
<FX>	{   F-RAM     "$8"       #070 solid }
<FX>	{   F-Swap    "$14"      #007 solid }
<FX>	{   F-Memory  "$8 + $14" #700 solid }
<FX>    }
<FX>}

One interesing extra configuration item is the background color of the "MemInfo" label.  Since the color, "dark red", is two words, it must be enclosed in double quotes.  But, the pair "-bg" and "dark red" but be enclosed as well.  To get around this, the pair is enclosed in curly braces, "{}", and the color is enclosed in double quotes.

The group "Key" is simply the key to the graph, to tell you what color means what.  It is organized into which type of memory, "RAM", "Swap", or "Memory" (total of other two).  And it tells whether it mean "Used" or "Free", lined or solid.  This one is currently set to update once every second, this may cause a bit of load, so if you use this you would probably want to slow that down.

The hash marks on the graph are set to every 5 megabytes (if you take one megabyte to be 1024 times 1000).  New to this graph is the large history.  It is 600 pixels updates, but the graph is only 300 pixels wide.  To view the history, you can click and drag on the graph with the left mouse button.  Since this graph moves scrolls left, click and drag to the right to see more.  To restor the graph's position to home, double click with the left mouse button.

To see this demo, <DEMO-IT>demos/meminfo2.omnirc</DEMO-IT>, click on it.



<SECTION>9:  atmstat.omnirc</SECTION>

This one shows the ability to do more interesting math operations on the fields, and to use the previous command output to generate deltas.  This one requires the command "atmstat" which is a command that come with FORE Systems' ATM adapters (hey I work for the company, I gotta get in a plug somewhere).  The output format of the command is:

<FX>PHY/ATM/AAL statistics:
<FX>         Output               Input                       Errors
<FX>       ATM     AAL*        ATM     AAL*    4B5B    4B5B     ATM    AAL*    AAL*
<FX>     Cells  CS-PDUs      Cells  CS-PDUs Framing Hdr-CRC VPI/VCI Pay-CRC   Proto
<FX> 107311332 10340969   19129848  3009185       0       0       0       0       0

Note that this one requires that the command is in your path.  That is it doesn't explicitly look for it in "/usr/fore/etc".  If this isn't so, you can rerun this after adding it to you path, or use the middle mouse button to select it.

<FX>{   group FORE {"FORE" top {"-font -*-helvetica-medium-r-normal--34-*" "-bg black" "-fore white"}} {} 60 top {}
<FX>    {   group Systems {"S Y S T E M S" top {"-font -*-helvetica-medium-r-normal--14-*" "-bg black" "-fore white"}}}
<FX>    {   group Band {" " top {"-font 5x7" {-bg "dark red"}}}}
<FX>}

<FX>{   group fa0 {"ATM cells/second for fa0:" top {{-foreground "dark red"}}} {"atmstat fa0"} 30 top {}
<FX>    {   group Transmit {"Transmit:" left {}} {} 30 left {}
<FX>	{   group Delta {"( %8 - =%8 ) / $s" left {"-fore red"}}}
<FX>    }
<FX>    {   group Receive {"Receive:" left {}} {} 30 left {}
<FX>	{   group Delta {"( %6 - =%6 ) / $s" left {"-fore red"}}}
<FX>    }
<FX>}

This one has some has some more complex extra parameters, but they're all relatively self explanatory.  New, though, is the "$s" symbol.  This will return the number of seconds since the last time this label was updated.  Also, introduced is the "=%n" symbol.  This returns the field given by whatever follows the "=", but from the previous run of the program, "atmstat fa0".  So the result of the whole expression is to take the current number, minus the previous one, and devide by the number of seconds elapsed.  This gives the ATM cells per second.

To see this demo, <DEMO-IT>demos/atmstat.omnirc</DEMO-IT>, click on it.



<SECTION>Hints and tipe</SECTION>

This section is a disorganized list of hints, tips, and ideas that I or other users have come up with.  If you have anything to contribute to this, please email it to me so that all OmniMoni users can benefit.

<SECTION>1</SECTION>  If you would like to have a graph have a maximum value and not scale with each change, you can graph an explicit number with a color of  ""  (clear) as in:

<FX>{   Test1  "10"  ""    lined }
<FX>{   Test2  "$1"  #0f0  lined }

This will always graph a "clear" line at 10 on the graph.  If a dynamic value exceeds 10, though, then the graph will begin to automatically scale again.


<SECTION>2</SECTION>  Using the configure command with the wm option you can change the title of the OmniMoni window to something else.  For example:

<FX>{   configure
<FX>    {wm title . "SomeName"}
<FX>}

Will change the OmniMoni window name to "SomeName".  This can help organize OmniMoni if you have multiple OmniMoni's running simultaneously.


<SECTION>3</SECTION>  If you have script that is identical in every way except the command it runs on you can use variable substitution to make things easier.  For example if you have some command that slowly produces output you could have a script that will periodically run "tail" on the output file.  If you then run that OmniMoni script as:

<FX>./omnimoni --r script_name.omnirc --set FILENAME output.1
<FX>./omnimoni --r script_name.omnirc --set FILENAME output.2
<FX>.
<FX>.
<FX>.

or course in the script you would need to have something like:

<FX>{   group Name {} {"tail $FILENAME"} 10 left {}
<FX>    { ...
<FX>    }
<FX>}

You could run it multiple time on different outputs easily.  You could also use this idea along with the previous idea about the window title.


<SECTION>4</SECTION>  To save CPU resources it is critical that you make the update delta a large as possible.  If you have a script that is only updated once every 60 seconds and you have the update delta set the the default of 1 second then you will still use a lot of CPU.  You should, in this case, set the update delta to 60000 (milliseconds) which is, of course, 60 seconds.

If you do this then you will get a flurry of CPU activity when the script is run and then zero usage between each update.



<SECTION>Closing Notes</SECTION>

Well, that's it for now.  I realize this script is far from complete and I'm actively working on it.  I hope you learned a bit from it and now somewhat understand what can be done with OmniMoni.  One thing I really want to do, but haven't gotten to yet, is creating a very complex, large omnirc file.  If you really wanted you could have one that monitors a LOT of information and completely fills your screen.

If you have any thoughts on the demo or the program itself, please send them to me.  I'm trying to add things to it, but outside input is crucial.  I can be found at, rvm@fore.com.

Please feel free to pass this program on to anyone you want.  Make sure you keep it in its original form, though; the tarred achive with all the supporting files.


			Thank you,

			Rainer Mager