On 12/04/2012 12:48, Paul.G wrote:
Hi All
New to this group, so hello to everybody.
I am currently working on creating a Array of Hashes, note it is a
work in progress. I appear to be getting some corruption when
inputting data with the pvdisplay, I can't see why this is the case.
I have put some print statements to see where I am going wrong and I
suspect the logic of the script is incorrect. Below is the script:
Scroll down further to see the output and hopefully it will make
sense what I am asking.
#!/usr/bin/perl
use strict;
use warnings;
my @vggroup;
my @PV;
my $PV=0;
my $Extents;
my $AllocatedPE;
my $rec = {};
my $href;
my $extent;
open(CMD,"/usr/sbin/vgdisplay -v vg03|");
while(<CMD>) {
if (/PV Name/) {
$PV = (split(/\s+/, $_))[3];
push @PV, $PV;
}
}
print "@PV \n";
foreach $PV (@PV) {
open(EXT,"/usr/sbin/pvdisplay $PV|");
while(<EXT>) {<-- This is aware I appear to be going wrong, scroll down
further.
print $_;<---
if (/Free PE/) {
$AllocatedPE = (split(/\s+/,<EXT>))[2];
$rec->{$PV} = $AllocatedPE;
print "$PV ";
print $rec->{$PV};
print " \n";
push @vggroup, $rec;
}
}
}
for $href (@vggroup) {
print "{ ";
for $extent ( keys %$href ) {
print "$extent=$href->{$extent} ";
}
print "}\n";
}
close(EXT);
close(CMD)
Result:
/dev/disk/disk46 /dev/disk/disk48 /dev/disk/disk47
/dev/disk/disk46 159
/dev/disk/disk48 159
/dev/disk/disk47 0
{ /dev/disk/disk46=159 /dev/disk/disk48=159 /dev/disk/disk47=0 }
{ /dev/disk/disk46=159 /dev/disk/disk48=159 /dev/disk/disk47=0 }
{ /dev/disk/disk46=159 /dev/disk/disk48=159 /dev/disk/disk47=0 }
/dev/disk/disk46 /dev/disk/disk48 /dev/disk/disk47
--- Physical volumes ---
PV Name /dev/disk/disk46
VG Name /dev/vg03
PV Status available
Allocatable yes
VGDA 2
Cur LV 1
PE Size (Mbytes) 64
Total PE 159
Free PE 0
/dev/disk/disk46 159<-- The lines in bold are getting inserted, when reading with
the pvdisplay. I should be seeing --> Allocated PE 0
Stale PE 0 Why is this
occurring?
IO Timeout (Seconds) default
Autoswitch On
Proactive Polling On
--- Physical volumes ---
PV Name /dev/disk/disk48
VG Name /dev/vg03
PV Status available
Allocatable yes
VGDA 2
Cur LV 1
PE Size (Mbytes) 64
Total PE 159
Free PE 0
/dev/disk/disk48 159
Stale PE 0
IO Timeout (Seconds) default
Autoswitch On
Proactive Polling On
--- Physical volumes ---
PV Name /dev/disk/disk47
VG Name /dev/vg03
PV Status available
Allocatable yes
VGDA 2
Cur LV 0
PE Size (Mbytes) 64
Total PE 159
Free PE 159
/dev/disk/disk47 0
Stale PE 0
IO Timeout (Seconds) default
Autoswitch On
Proactive Polling On
Hi Paul and welcome to the list.
I can see a few things wrong with your code, but I have only a Windows
machine so cannot test any changes I am suggestion so please beware.
The reason you get the marked line in your output is because that is
what you have written. This loop
open(EXT,"/usr/sbin/pvdisplay $PV|");
while(<EXT>) {
print $_;
if (/Free PE/) {
$AllocatedPE = (split(/\s+/, <EXT>))[2];
$rec->{$PV} = $AllocatedPE;
print "$PV ";
print $rec->{$PV};
print " \n";
push @vggroup, $rec;
}
}
reads a line from the pvdisplay output and checks whether it contains
'Free PE'. If it does, this
$AllocatedPE = (split(/\s+/, <EXT>))[2];
reads another line (the 'Allocated PE' line), splits it on white space
and puts the third field - the extent - into $AllocatedPE. The code then
goes on to add a single hash element to $rec and then print the volume
name and extent.
The line read within the call to split is never displayed, and the loop
goes on to read and display the line after it in the while loop.
Another problem is that you are pushing the same hash reference $rec
onto @vggroup several times. There is no need for the array, as the hash
holds the information on all the volumes in the group on its own.
Other advice that may help is:
- Perl variables generally use lower-case letters and underscores, and
should be declared at the point of first use
- Lexical file handles should be used with the three-argument form of
open, and the status of /all/ opens should be checked before the file
handle is used
- By default the split operator splits $_ on whitespace, so split on its
own returns a list of separate non-whitespace fields found in $_. This
is usually what is wanted, as is the case here
- There may well be a module already written to do this. It is worh a
look at http://search.cpan.org unless your purpose is to learn the language
Below is a refactored version of your program taking these things into
account. As I explained I am unable to test it so I can only confirm
that it compiles.
HTH,
Rob
use strict;
use warnings;
open my $cmd, '-|', "/usr/sbin/vgdisplay -v vg03" or die $!;
my @pv;
while (<$cmd>) {
if (/PV Name/) {
my $pv = (split)[2];
push @pv, $pv;
}
}
print "@pv\n";
my $rec;
foreach my $pv (@pv) {
open my $ext, '-|', "/usr/sbin/pvdisplay $pv" or die $!;
while(<$ext>) {
print;
if (/Allocated PE/) {
my $allocated_pe = (split)[2];
$rec->{$pv} = $allocated_pe;
print "$pv => $allocated_pe\n";
}
}
}
use Data::Dumper;
print Dumper $rec;
--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/