hengesystems
asked on
Help need with Bash script to read numbers from various files and output these to html table.
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/vm hba0\: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</T D><TD>MEM< /TD><TD>DI SK</TD></T R>"
echo "<TR><TD></TD><TD>SHARES</ TD><TD>SHA RES</TD><T D>SHARES</ TD></TR>"
echo "<TR></TR>"
for i in $ACTIVELIST; do
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm hba0\:0\:0 | read line1; read line2; echo "$line2" | cut -d" " -f1 ; `
CPUSHARES=`cat /proc/vmware/vm/$i/cpu/sha res`
NAME=`cat /proc/vmware/vm/$i/names | cut -d\" -f6`
MEMSHARES=`cat /proc/vmware/vm/$i/mem/sha res`
echo "<TR><TD>$NAME</TD><TD>$CP USHARES</T D><TD>$MEM SHARES</TD ><TD>$DISK SHARES</TD ></TR>"
done
John.
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/vm
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
done`
echo "<HTML><BODY>"
echo "<TABLE width=300 border=1>"
echo "<TR><TD>VM</TD><TD>CPU</T
echo "<TR><TD></TD><TD>SHARES</
echo "<TR></TR>"
for i in $ACTIVELIST; do
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm
CPUSHARES=`cat /proc/vmware/vm/$i/cpu/sha
NAME=`cat /proc/vmware/vm/$i/names | cut -d\" -f6`
MEMSHARES=`cat /proc/vmware/vm/$i/mem/sha
echo "<TR><TD>$NAME</TD><TD>$CP
done
John.
#!/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
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
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
ASKER
Hi,
Thanks for that, however
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm hba0\: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
Thanks for that, however
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm
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
ASKER
Hi,
I played around and the following works:
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm hba0\:0\:0 | tail -1 | cut -d" " -f7`
works.
So if anyone can help me with 2 and 3 that would be great.
Thanks.
I played around and the following works:
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm
works.
So if anyone can help me with 2 and 3 that would be great.
Thanks.
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
perl -ne 'if( !/\S/..0 and /\S/..0 ){ my(@s)=split; push @{$c[$_]},$s[$_] for 0..$#s }else{ print} END{@$_ = map{"*"x($_+1)}sort{$_->[$
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
ASKER
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.
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.
ASKER
Woops, also discovered that
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm hba0\: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.
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm
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.
Use
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm hba0\:0\:0 | tail -1 | tr -s " " | cut -d" " -f2`
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm
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/vm hba0\:0\:0 | awk '{print $1}'`
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{$_->[$
DISKSHARES=`tail -1 /proc/vmware/vm/$i/disk/vm
ASKER
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/vm hba0\:0\:0 | tail -1 | awk '{print $1}'`
worked well and nice and simple.
Thankyou kindly.
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/vm
worked well and nice and simple.
Thankyou kindly.
> 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/vm hba0\:0\:0
(replacing $i by a valid value, for obvious reason:)
please post the result of:
cat /proc/vmware/vm/$i/disk/vm
(replacing $i by a valid value, for obvious reason:)
ASKER
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
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
#!/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"
}
@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
print "\n"
}
for i in $ACTIVELIST; do
DISKSHARES=`awk '(NR==2){print $1}' /proc/vmware/vm/$i/disk/vm hba0\:0\:0 `
done
DISKSHARES=`awk '(NR==2){print $1}' /proc/vmware/vm/$i/disk/vm
done
ASKER
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
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
ASKER
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.
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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.
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.
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+) /];
"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
ASKER
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{$m ax[$_]/$mi n[$_],'*'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!
Im making great progress now!
Just trying to get <TD> and </TD> before and after each column value.
printf"<td>%-*s"x4,10,$c->
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!
printf"<td>%-*s</td>"x4
ASKER
Cheers.
Working beautifully.
Thanks.
Working beautifully.
Thanks.
DISKSHARES=`cat /proc/vmware/vm/$i/disk/vm
>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