1821615 Members
4048 Online
109633 Solutions
New Discussion юеВ

Using df -k on Perl

 
SOLVED
Go to solution
Steve_617
Advisor

Using df -k on Perl

I have sent a df -k to a tmp1 file
I then try and loop through the file and send each line to an aray.
I then want to print out the % field and do a test to see if the disk space is greater than 80% so I can perform a task on that, but for some reason when I split the array using qw(@aray_name), it does not give me any data.

Any advice
12 REPLIES 12
H.Merijn Brand (procura
Honored Contributor

Re: Using df -k on Perl

qw(@array) will return a list with ONE element: '@array'

qw// will Quote Words: any sequence of non blanks is considered a word in that, except the ',' for which you will probably get a warning

what you probably meant was to split up each line into fields, where the fields are seperated by spaces:

my @list = split /\s+/;

In a more full context:

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5] > 80 and print;
}

HTH, Enjoy, Have FUN! H.Merijn

Enjoy, Have FUN! H.Merijn
Steve_617
Advisor

Re: Using df -k on Perl

Thanks

I have assigned the array now to a second array and then substituted the % sign with //.
This works, but is there a simpler and quicker way to do so.
I get an error message that 46% is not a numeric value.
H.Merijn Brand (procura
Honored Contributor

Re: Using df -k on Perl

That's GOOD! You are using warnings!
That is a bonus for you.

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5] =~ m/(\d+)/ && $1 > 80 and print;
}

is a cleaner way, or you can use the less maintainable way of looking at the value in string context:

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5] =~ m/^([89]\d|1\d\d)%$/ and print;
}

this will match all percentages from 80 and up.

FYI the *dirty* way to get rid of this warning (since you know it is OK) is to (temporarily) disable warning:

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
no warnings;
$f[5] > 80 and print;
}

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Steve_617
Advisor

Re: Using df -k on Perl

Why can I not do the following

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5]=~tr/\%//g and print; ### my changes
}


My goal is to have an output
/usr 88%
/var 94%
H.Merijn Brand (procura
Honored Contributor

Re: Using df -k on Perl

If that's your goal, why not simply

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
print "@f[0,5]\n";
}

or

local @ARGV = ("df -k |");
while (<>) {
print +(split/\s+/)[0,5],"\n";
}

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
H.Merijn Brand (procura
Honored Contributor

Re: Using df -k on Perl

that 0,5 should be 1,5 in your case, where you want to see the mount point, and not the locical volume.

From the command line, that might even shorter look like:

a5:/u/usr/merijn 105 > df -k | perl -anle'print"@F[1,5]"'
Mount %used
/ 17%
/data 57%
/home 8%
/opt 95%
/pro 97%
/stand 26%
/tmp 8%
/u 50%
/usr 86%
/var 13%
/wrk 67%
a5:/u/usr/merijn 106 >

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Steve_617
Advisor

Re: Using df -k on Perl

Just to come back to my previous question.
Why can I not do the following

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5]=~tr/\%//g > 80 and print; ### my changes
}

I would like to print all the parttions greater than 80% but in the format
/usr 80%
/var 92%
H.Merijn Brand (procura
Honored Contributor
Solution

Re: Using df -k on Perl

firstly because tr does not give you back the value of the variable changed, but it returns the number of characters changed
secondly because tr/// is not the same as s/// and tr/// does not recognize the /g option (tr/// or the equivalent y/// only know of the options 'c' - complement the search list, 'd' - delete found but unreplaced characters, and 's' - squash duplicate replaced characters.

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5]=~tr/\%//g > 80 and print; ### my changes
}

that's why I gave you the second example

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5] =~ m/(\d+)/ && $1 > 80 and print;
}

but if you prefer to delete the '%' from the original string, you'd better do

local @ARGV = ("df -k |");
while (<>) {
my @f = split /\s+/;
$f[5] =~ tr/%//d && $f[5] > 80 and print;
}

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Steve_617
Advisor

Re: Using df -k on Perl

Thanks for all your help.
The first to responses gave me an option to give your help a rating, however I the last few replies there is no option to rate your responses..

If I may ask you what does the pipe do after df -k |.

I have just done a PErl course at HP but it seems I still have a long way to go, as I don't recognise most of the stuff you have shown me

Regards
Steve
H.Merijn Brand (procura
Honored Contributor

Re: Using df -k on Perl

Being a perl5 porter (someone in the perl5 source code maintainer team), I probably know more about Perl than the avarage perl scripter here on the forum, so don't feel bad about it when you see `new' things. I tend to use what I know.

The pipe however is a `standard' feature.

open my $pipe, "command |" or die "cannot pipe: $!";

opens a pipe from the executed "command", which can be any unix command - like ps, who, ls, du, bdf, ..., and pipes it output to the handle you opened it to ($pipe). Now when you read from $pipe, like in

my $line = <$pipe>;

the line is the next line as generated by the pipe command.

You can learn more about it in the perl man pages:

man perlfunc
man perlopentut
perldoc -f open

If you show up as "Author", I don't know why you cannot assign points. Do you need help? We can get help from HP people on anything causing trouble in the forum.

HTH, Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Steve_617
Advisor

Re: Using df -k on Perl

HERE IS MY SCRIPT AND ITS OUTPUT
#!/usr/bin/perl -w
`df -k > /tmp/tmp2`;
open RF, "< /tmp/tmp2";
while($line=)
{
@LIST=(split/\s+/,($line)) ;
@STEVE=($LIST[4])=~s/\%//;
#print @STEVE,"\n";
if ($LIST[4]>80)
{
print "BIG PROBLEM ";
print $LIST[5]," ",$LIST[4],"\n";
}
elsif ($LIST[4]>30 )
{
print "LITTLE PROBLEM ";
print $LIST[5]," ",$LIST[4],"\n";
}
elsif ($LIST[4]>0 )
{
print "NO PROBLEM ";
print $LIST[5]," ",$LIST[4],"\n";
}
}
close RF;
$SS=`ps -ef |grep csi |grep SpectroSERVER |grep -v grep`;
$ARC=`ps -ef |grep csi |grep ArchMgr |grep -v grep`;
$VBOA=`ps -ef |grep csi |grep VBOA |grep -v grep`;
$LOC=`ps -ef |grep csi |grep LocServer |grep -v grep`;
$SDPM=`ps -ef |grep csi |grep processd |grep -v grep`;
print $SS,"\n";
print $ARC,"\n";
print $VBOA,"\n";
print $LOC,"\n";
print $SDPM,"\n";
exit;


AND THE OUTPUT
$ ./Test1.pl
Name "main::STEVE" used only once: possible typo at ./Test1.pl line 7.
Argument "capacity" isn't numeric in numeric gt (>) at ./Test1.pl line 9, line 1.
NO PROBLEM / 4
LITTLE PROBLEM /usr 43
NO PROBLEM /var 12
NO PROBLEM /var/run 1
NO PROBLEM /tmp 1
NO PROBLEM /home1 6
NO PROBLEM /csi 7
BIG PROBLEM /swap 100
NO PROBLEM /export/home 21
BIG PROBLEM /cd1 100
spectrum 8520 8488 1 Mar 18 ? 322:25 /csi/spectrum/SS/SpectroSERVER

spectrum 8531 8488 0 Mar 18 ? 7:25 /csi/spectrum/SS/DDM/ArchMgr

spectrum 8513 8488 0 Mar 18 ? 0:05 /csi/spectrum/bin/VBOA/osagent

spectrum 8497 8488 0 Mar 18 ? 0:05 /csi/spectrum/LS/LocServer

root 8488 1 0 Mar 18 ? 0:06 /csi/spectrum/lib/SDPM/processd --start

$

BAR THE ERROR AT THE TOP IT GIVES ME WHAT I WANT BUT ITS VERY CLUMBSY COMPARED TO YOUR EXAMPLE. WHAT I DO ABOVE IS EASY TO DO IN KORN BUT I WOULD LIKE TO GET TO KNOW THE POWER OF PERL, THAT IS WHY I WOULD LIKE TO DO IT IN PERL!!!
ANY SUGESTIONS
H.Merijn Brand (procura
Honored Contributor

Re: Using df -k on Perl

Without looking deeper, first thing I'd do is a small rewrite to safer code.

1. Don't use full-caps variables unless they serve a special cause
2. use strict;
3. use lexicals (my $var)
4. prevent duplicate code (the list of greps)
5. @STEVE is a list $STEVE is a scalar
6. use whitespace ($var > 80)
7. use interpolation where appropriate "blah $var foo"
8. prevent external files if possible (open)
9. use builtin functions instead of external processes (grep)

--8<---
#!/usr/bin/perl

use strict;
use warnings;

open my $rf, "df -k |";
while (<$rf>) {
my @list = split /\s+/;
(my $steve = $list[4]) =~s/\%//; # Look at this change closely
#print "$steve\n";
if ($steve > 80) {
print "BIG PROBLEM $list[5] $list[4]\n";
}
elsif ($steve > 30) {
print "LITTLE PROBLEM $list[5] $list[4]\n";
}
elsif ($steve > 0) {
print "NO PROBLEM $list[5] $list[4]\n";
}
}
close $rf;

# I'd personally use Proc::ProcessTable
chomp (my @ps = grep m/csi/ => `ps -ef`);
my @ss = grep /SpectroSERVER/, @ps;
my @arc = grep /ArchMgr/, @ps;
my @vboa = grep /VBOA/, @ps;
my @loc = grep /LocServer/, @ps;
my @sdpm = grep /processd/, @ps;

print @ss, "\n", @arc, "\n", @vboa, "\n", @loc, "\n", @sdpm, "\n";
-->8---

The latter part, presuming you want these processes to be printed, could more ligible be written as

print grep /\b(SpectroSERVER|ArchMgr|VBOA|LocServer|processd)\b/ => `ps -ef`;

which is the same as those 8 lines I wrote converted from your code

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn