Solved

Help need with Bash script to read numbers from various files and output these to html table.

Posted on 2006-11-13
22
261 Views
Last Modified: 2010-04-22
I am trying to complete the following script which reads files from various directories and produces an HTML table.

The script is mostly working, however I would like the following adjustments:


1.  the  DISKSHARES variable is not evaluating to anything.  It needs more complex file preprocessing.  The other variables simply read the relevant file.

/proc/vmware/vm/$i/disk/vmhba0\:0\:0  will contain something like:

    shares       cmds      reads
      1000     163505      10465

I would like DISKSHARES to equal 1000 in this case.

At the moment, DISKSHARES is just blank. Im not really sure what I am doing with the read command.

I would also like the script to display the current date and time at the top.

2. Once DISKSHARES is working, I would like an additional table outputed below this to  display relative values using asterixes rather than numbers  

For example:

Instead of

VM         CPU           MEM            DISK
             SHARES      SHARES       SHARES

machine1   100        3                 5
machine2   200        2                 15
mashine3   300        1                 10


It would display:


VM         CPU           MEM            DISK
             SHARES      SHARES       SHARES

machine1   *          ***               *
machine2   **        **                 ***
mashine3   ***      *                   *


Hope someone can help.


Here is the script so far:

#!/bin/bash

echo Content-type: text/plain
echo ""

WORLDLIST=`ls -1 /proc/vmware/vm/`
ACTIVELIST=`for i in $WORLDLIST; do cat /proc/vmware/vm/$i/cpu/run-times | grep vmm0 | cut -d" " -f4 ;
done`
echo "<HTML><BODY>"
echo "<TABLE width=300 border=1>"
echo "<TR><TD>VM</TD><TD>CPU</TD><TD>MEM</TD><TD>DISK</TD></TR>"
echo "<TR><TD></TD><TD>SHARES</TD><TD>SHARES</TD><TD>SHARES</TD></TR>"
echo "<TR></TR>"
 
for i in $ACTIVELIST; do
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0| read line1; read line2; echo "$line2" | cut -d"   " -f1 ; `
CPUSHARES=`cat /proc/vmware/vm/$i/cpu/shares`
NAME=`cat /proc/vmware/vm/$i/names | cut -d\" -f6`
MEMSHARES=`cat /proc/vmware/vm/$i/mem/shares`
echo "<TR><TD>$NAME</TD><TD>$CPUSHARES</TD><TD>$MEMSHARES</TD><TD>$DISKSHARES</TD></TR>"
done


John.
0
Comment
Question by:hengesystems
  • 11
  • 7
  • 2
  • +2
22 Comments
 
LVL 45

Expert Comment

by:sunnycoder
ID: 17928794
Hi hengesystems,

DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | tail -1 | cut -f1`
>I would also like the script to display the current date and time at the top.
date

man date for more information

re2: Not trivial to accomplish using bash ... unless it is ok with you to use a fixed scale, e.g. print num/10 asteriks ... some other scripting language such as perl might be more convenient for this - not sure though - not much familiar with perl

Cheers!
sunnycoder
0
 
LVL 84

Expert Comment

by:ozo
ID: 17929554
#!/usr/bin/perl
while( <DATA> ){
    if( !/\S/..0 and /\S/..0 ){
        my(@s)=split;
        push @{$c[$_]},$s[$_] for 0..$#s
    }else{
        print;
    }
}

@s=map{'*'x$_}1..@c;
@$_ = @s[sort{$_->[$a]<=>$_->[$b]} 0..$#$_] for @c[1..3];
for $i ( 0..$#{$c[0]} ){ printf"%-12s",$c[$_][$i] for 0..3; print"\n"; }
__DATA__
VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   100        3             5
machine2   200        2             15
mashine3   300        1             10
0
 

Author Comment

by:hengesystems
ID: 17929800
Hi,

Thanks for that, however

DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | tail -1 | cut -f1`

This didnt work.  It is displaying "      1000     163505      10465" instead of just 1000

Thanks for the Perl script, however not sure how to use it.  I created a perl file, made it executable and piped  this into it:
VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   100        3             5
machine2   200        2             15
mashine3   300        1             10

however there was no output.

Dont mind how 2 and 3 are done really, but would appreciate some more guidance here.  I just copied some of the bash script and made minor mods...  I understand even less of how the perl script works.   Is c[1..3] because there are 3 columns?

Thanks

0
 

Author Comment

by:hengesystems
ID: 17929910
Hi,

I played around and the following works:

DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | tail -1 | cut -d" " -f7`

works.

So if anyone can help me with 2 and 3 that would be great.

Thanks.
0
 
LVL 84

Expert Comment

by:ozo
ID: 17929915
you can pipe to it like this:
perl -ne 'if( !/\S/..0 and /\S/..0 ){ my(@s)=split; push @{$c[$_]},$s[$_] for 0..$#s }else{ print} END{@$_ = map{"*"x($_+1)}sort{$_->[$a]<=>$_->[$b]} 0..$#$_ for @c[1..3]; for $i ( 0..$#{$c[0]} ){ printf"%-12s",$c[$_][$i] for 0..3; print"\n"; }}' << END
VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   100        3             5
machine2   200        2             15
mashine3   300        1             10
END

Yes, 1..3 is because there are 3 columns
it could have been 1..$#c to make it work on any number of columns
0
 

Author Comment

by:hengesystems
ID: 17929991
Sorry if this is a bit ignorant, can you spell it out for me.

Im not sure what perl file I need to make up and if I still need the bash script.

I have a bash script that outputs this:
VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   100        3             5
machine2   200        2             15
mashine3   300        1             10

in HTML (now working with diskshares correcytly)  and another one that has not HTML, but with spaces in between the columns.

Thanks.

0
 

Author Comment

by:hengesystems
ID: 17930015
Woops, also discovered that
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | tail -1 | cut -d" " -f7`

only works if the first number is 1000   if it is less digits, say 300  I get a space,   I cant work out how to get cut to work with any number of spaces as delimiter.. (default of tab doesnt work, as they seem to be spaces)....  I need some other function I think.

0
 
LVL 58

Expert Comment

by:amit_g
ID: 17932710
Use

DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | tail -1 | tr -s " " | cut -d" " -f2`

0
 
LVL 84

Expert Comment

by:ozo
ID: 17934817
on the command line
pipe | perl -ne 'if( !/\S/..0 and /\S/..0 ){ my(@s)=split; push @{$c[$_]},$s[$_] for 0..$#s }else{ print} END{@$_ = map{"*"x($_+1)}sort{$_->[$a]<=>$_->[$b]} 0..$#$_ for @c[1..3]; for $i ( 0..$#{$c[0]} ){ printf"%-12s",$c[$_][$i] for 0..3; print"\n"; }}'


DISKSHARES=`tail -1  /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | awk '{print $1}'`
0
 

Author Comment

by:hengesystems
ID: 17936392
Hi ozo,

Thanks for the perl line above.  Just tested it and   I have realised that I have not been explicit enough.    I want the stars to show relative values not based on ranking, but based on total for that particular column.  

For example

VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   100        3             5
machine2   200        2             15
mashine3   300        4             100

This would come out as:

VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   *        ***          *
machine2   **      **            ***
mashine3   ***    ****        ********************


Dont know if that is possible?

By the way,  Added tail to DISKSHARES - ie
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0 | tail -1 | awk '{print $1}'`

worked well and nice and simple.

Thankyou kindly.
0
 
LVL 51

Expert Comment

by:ahoffmann
ID: 17960189
> only works if the first number is 1000   if it is less digits, say 300  I get a space,

please post the result of:

   cat /proc/vmware/vm/$i/disk/vmhba0\:0\:0

(replacing $i by a valid value, for obvious reason:)
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:hengesystems
ID: 17969862
Here it is,

there are actually two lines

    shares       cmds      reads     KBread     writes  KBwritten   cmdsAbrt     busRst    paeCmds  paeCopies  splitCmds  splitCopies   issueAvg   totalAvg     active     queued          virtTime
      1000    1755525      78126     579677    1677399   17242983          0          0          0          0          0             0   42008741  128565936          0          0   520605772064329

Hope this helps.

Cheers
0
 
LVL 84

Expert Comment

by:ozo
ID: 17970011
#!/usr/bin/perl
@max=(1)x3;
while( <> ){
    if( !/\S/..0 and /\S/..0 ){
        push @c,[split];
        for( 1..3 ){
            $max[$_]=$c[-1][$_] if $c[-1][$_]>$max[$_];
        }
     }else{
        print;
     }
}
@t=(0,3,4,20);
for$c( @c ){
    printf "%-12s"x4,$c->[0],map{'*'x(0.5+$c->[$_]*$t[$_]/$max[$_])}1..3;
    print "\n"
}
0
 
LVL 51

Expert Comment

by:ahoffmann
ID: 17970784
for i in $ACTIVELIST; do
  DISKSHARES=`awk '(NR==2){print $1}' /proc/vmware/vm/$i/disk/vmhba0\:0\:0`
done
0
 

Author Comment

by:hengesystems
ID: 17970936
Thanks ozzo!

very close,

execept the following input

VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1   100        3             5
machine2   200        2             15
mashine3   300        1             10
machine4   400        4             30

outputs this:

VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1    *           ***         ***
machine2    **         **           **********
mashine3    **         *             *******
machine4    ***       ****       ********************



Yet it should give this:

VM         CPU         MEM          DISK
           SHARES      SHARES       SHARES

machine1    *            ***        *
machine2    **          **          ***
mashine3    ***        *            **
machine4    ****      ****      ******


ie each column always has a single star in it.

To make it easier, you dont have to worry about fractions/rounding. The smallest number in any given column will always divide evenly into all other numbers in that column.

Thanks again for your help.  It is almost perfect


0
 

Author Comment

by:hengesystems
ID: 18002834
Hi Ozzo,

I am trying to work out why the second column above worked using your code, but the first column doesnt display the stars correctly.

I Played around with this line:
 $max[$_]=$c[-1][$_] if $c[-1][$_]>$max[$_];


but nothing I changed seemed to make the first column print the stars correctly.

Hope you have some ideas.  

I would like to sort this out and close this question.  

You have been a great help so far

Thanks.
0
 
LVL 84

Accepted Solution

by:
ozo earned 500 total points
ID: 18004233
#!/usr/bin/perl
@max=(1)x3;
while( <> ){
    if( !/\S/..0 and /\S/..0 ){
        push @c,[split];
        for( 1..3 ){
            $min[$_]=$c[-1][$_] if !$min[$_]||$c[-1][$_]<$min[$_];
            $max[$_]=$c[-1][$_] if $c[-1][$_]>$max[$_];
        }
     }else{
        print;
     }
}
for$c( @c ){
    printf "%-*s  "x4,10,$c->[0],map{$max[$_]/$min[$_],'*'x($c->[$_]/$min[$_])}1..3;
    print "\n"
}
0
 

Author Comment

by:hengesystems
ID: 18007535
Works fine on the files I gave.

Thankyou.

THink I need to learn some pear and understand how the delimiters work in your example.

as im geting division by zero errors when I feed it this:


Name     CPU    MEM    DISK
         Shares Shares Shares

DebFire2    250 500 1000
Coldfusion    1000 1400 1000
Hugo    1000 4000 1000
Peak    500 800 1000
Humans     6000 8000 8000
Spam Box    500 2000 1000
BAW    500 1000 1000

Thanks for your great help.

0
 
LVL 84

Expert Comment

by:ozo
ID: 18008429
It is splitting on space and reading
"Spam" as the machine, "Box" as CPU, 500 as MEM and 1000 as DISK
When it tries to use "Box" as a number, it treats it as 0
That case might be better handled with something like
push @c,[/\b(.*?)\s+(\d+)\s+(\d+)\s+(\d+)/];
0
 

Author Comment

by:hengesystems
ID: 18010226
Fantastic.

Im making great progress now!

Just trying to get <TD> and </TD> before and after each column value.


printf"<td>%-*s"x4,10,$c->[0],map{$max[$_]/$min[$_],'*'x($c->[$_]/$min[$_])}1..3;
    print "</td>\n"
}

I can get the one at the start of each column and end of the row, but cant work out how to get one at the end of the 1st, 2nd, 3rd and 4th coumns.

Ie its looking like this now:


<td>Coldfusion  <td>****      <td>**                <td>*       </td>
<td>Hugo         <td>****       <td>********   <td>*       </td>
<td>Peak         <td>**            td>*                   <td>*       </td>
         

Once that is done, it will be complete!

0
 
LVL 84

Expert Comment

by:ozo
ID: 18010252
printf"<td>%-*s</td>"x4
0
 

Author Comment

by:hengesystems
ID: 18010268
Cheers.

Working beautifully.

Thanks.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now