Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Re^3: Getting error while executing the script

by blue_cowdawg (Monsignor)
on Jun 14, 2012 at 14:11 UTC ( #976219=note: print w/replies, xml ) Need Help??

in reply to Re^2: Getting error while executing the script
in thread Getting error while executing the script

Where do I begin with this script? There's all sorts of things wrong with it.

First off your script should have the following two pragmas right from the start:

use strict; use warnings;
this will aid you in troubleshooting your code by forcing you to use proper techniques so far as scoping, etc. etc. etc.

#Checks the type of OS here $OS = `uname -s`; print ("The Operating System is $OS"); if ($OS == SunOS ) { &< snip1 &<

You're missing a few things here... A rewrite should look like:

my $os = `uname -s`; # why capital? chomp $os; # get rid of the EOL character, you'll be glad +you did. printf "Operating system: %s\n",$os; if ( $os eq 'SunOS' ) { # this is where EOL needs to be gone... &< snip! &<

Next bit of headache:

$DF = `df -h $FILESYSTEM | grep -v "Filesystem" | sed -e "s/%//g"| +awk '{print $5}'`; print ("The file system $ FILESYSTEM usage is $DF % \n");
If you are programming in Perl why the h3!! are you invoking grep and awk? Secondly using df -h is going to give you "human readable" output and is useless in the context you are trying to use it in namely doing numerical comparisons. df -k might make more sense, but a straight up df is probably what you really need. Since you are picking off the percentage of use that's the only way you are getting away with this. Try this:
my $cmd=sprintf("df -k %s |",$FILESYSTEM) #note the trailing pipe in +the format open PIPE,$cmd or die "$cmd: $!"; my $junk=<PIPE>; # get rid of the first line.. it's junk. # # Could probably use /[\s]+/ but... my @df=split(/[\s\n\t]+/,<PIPE>) close PIPE; # done with this. my $df=$df[4]; #keep in mind the scalar $df is different than the arr +ay @df chomp $df; # just for grins $df =~ s/\%//g; # strip the % printf "File system %s is %d%% used\n",$FILESYSTEM,$df

My next nit to pick:

$DU = `du -sh $FILESYSTEM | sort -rn | head -20`;
I'm not so sure that what you think this is doing is what is really happening. By doing a du -sh you are getting a summary of usage for that directory and not a list of the subdirectories with their usage. Using the -h flag also invalidates the numerical sorting you are trying to do. Here's my rewrite:
open PIPE, sprintf("du -s %s/* |,$FILESYSTEM) or die $!; my @raw=<PIPE>; chomp @raw; my @summary=(); foreach my $line(@raw){ my($blocks,$subdir)=split(/[\s+]/,$line); push @summary,{ blocks=>$blocks, subdir=>$subdir }; } @summary=sort { $b->{blocks} <=> $a->{blocks} } @summary; printf "%s\n",join("\n", map { sprintf("%d\t%s",$_->{blocks},$_->{subdir}) } @summary[0..19] );
Now I realize I've thrown some advanced stuff at ya, but I'll try and explain what's going on here. I've opened a pipe to collect the stdout of the command (I'll use /foo for a file system example)  du -s /foo/* and I've slurped it into an array @raw. I then iterate over that array and create an array of hashes (you'll hopefully see why in a second) where I've hashed the values for the subdirectory path and the number of blocks the subdirectory uses. (Actually it is files and subdirectories)

Next thing I'm doing is sorting on the number of blocks in reverse. The bit that looks like { $b->{blocks} <=> $a->{blocks} } is an anonymous sub that governs how the sort function works. The normal behavior for sort would look like $a cmp $b which is to say an alphabetic forward sort rather than the numerical reverse sort we are doing.

Here is where things get a bit snazzy and tricky at the same time. map { } @summary... iterates over the array passed to it. The bit about @summary[0..19] passes an array slice consisting of the first 20 elements in that array. The logic inside the map  map { sprintf("%d\t%s",$_->{blocks},$_->{subdir})} is putting the hash back together again and join("\n",... is taking the array coming out of map and making one big scalar (string) out of it.

Having said that... just remember that in Perl TIMTOWTDI!

Peter L. Berghold -- Unix Professional
Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://976219]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2017-06-25 21:11 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (571 votes). Check out past polls.