Parsing nfsstat(1) for only version X information
Posted Thu, 06 Apr 2006
nfsstat | sed -ne '/Version 3/,/^$/p'sed++
When I was bored (at 4 am, no-less), I kept trying to parse this information out using some crazy tricks with 'x' (swap pattern/hold) and other stuff, but I forgot the fact that regexps are valid addresses. So, we can print anything between 'Version 3' and blank lines, anywhere in our output.
The next thing I want to try with this is to automagically parse nfsstat output into a format that is more machine readable, this will probably be using awk or perl, seeing as how doing it with sed may hurt my brain a bit. Furthermore, trying to read the sed that did said operations would be somewhat intense ;)
The output looks something like this, on Solaris 9:
Version 3: (535958 calls) null getattr setattr lookup access readlink 0 0% 242223 45% 20606 3% 52504 9% 20025 3% 41 0% read write create mkdir symlink mknod 14138 2% 146618 27% 5525 1% 145 0% 337 0% 0 0% remove rmdir rename link readdir readdirplus 6279 1% 7 0% 1539 0% 1518 0% 1606 0% 6587 1%Parsing this would mean generating a tree-like dictionary. In perl, it may look like:
%foo = (
'Version 3' => {
null => 0,
getattr => 242223,
setattr => 20606,
lookup => 52504,
# .... etc ...
}
)
Should be simple enough, we'll see what happens next time I get bored.
It works for me on solaris and hp-ux. Any tips on how to simplify?
#!/usr/local/bin/perl -w
use Net::Rexec 'rexec';
use Data::Dumper;
$userid = 'foo';
$password = 'foo';
$command = 'nfsstat -ns | sed -ne \'/Version 3/,/^$/p\'';
$host = $ARGV[0];
($rc, @output) = rexec($host, $command, $userid, $password);
if($rc == 0)
{
$res{totcalls} = $output[0]; # First line contains total calls
$res{totcalls} =~ s/\D//g;
$line = 1;
while($line < $#output)
{
@fields = split /\s+/,$output[$line]; # First field names on one line
$output[$line+1] =~ s/\d+%//g; # Get rid of percentage values
@values = split /\s+/,$output[$line+1]; # On next line field values
for($field=0;$field <= $#fields;$field++)
{
print "$fields[$field] -> $values[$field]\n";
$res{$fields[$field]} = $values[$field];
}
$line+=2;
}
print "totcalls:$res{totcalls} read:$res{read} write:$res{write}\n";
}
elsif($rc == 1)
{
print "ERROR exec\n";
}
else
{
print "ERROR fork\n";
}