Cannot execute Unix command in a simple perl script

Am trying to lean perl scripting in Unix OS to automate my tasks.

Please find the below perl script i have tried

#!/usr/bin/perl -w
print "Please Enter the VG name to be checked:";
$A = <>;
print "Please Enter the free size to be checked in GB:";
$B = <>;
        $vgcheck = `vgdisplay -v 2> /dev/null |grep -i "vg name" |grep -i $A`;
        $vgcheckc = `echo "$vgcheck" |wc -c`;
        print "$vgcheckc";
        if ($vgcheckc > 0)
                {
                $FREE = `vgdisplay $A | grep -i 'Free PE' | awk '{print $NF}'`;
                print $FREE;
                $PESIZE = `vgdisplay $A |grep -i 'PE Size' |awk '{print $NF}'`;
                print $PESIZE
                $total = $FREE * $PESIZE;
                $check = $B * 1024;
                        if ($total > $check)
                        {
                        print "Required Free Space is there in VG $A.. Please proceed to extend the Filesystem as requested\n";
                        print "TOtal free Space in VG $A is : $total MB";
                        }
                        else
                        {
                        print "Required Free Space is NOT there in VG $A..New LUNS are needed. CR must be raised \n";
                        print "Total free Space in VG $A is : $total MB\n";
                        $diff = $check - $total;
                        print "$diff MB of lun must be added to vg $A to proceed with Filesystem Extension\n";
                        }
                }
        else
                {
                print "Please give the correct VG name. The given VG is either not present nor It is NOT Activated\n";

I want to get the "free pe" and "pe size" from the vgdisplay command. but the whole vgdisplay command O/P is being stored to the variable

$FREE = `vgdisplay $A | grep -i 'Free PE' | awk '{print $NF}'`;

O/P of the perl program

$ perl testperl.pl
Please Enter the VG name to be checked:vgesar
Please Enter the free size to be checked in GB:20
41
Use of uninitialized value in concatenation (.) or string at testperl.pl line 11, <> line 2.
sh[2]: Syntax error at line 2 : `|' is not expected.
--- Volume groups ---
VG Name                     /dev/vgesar
VG Write Access             read/write
VG Status                   available, exclusive
Max LV                      255
Cur LV                      1
Open LV                     1
Max PV                      100
Cur PV                      2
Act PV                      2
Max PE per PV               1599
VGDA                        4
PE Size (Mbytes)            32
Total PE                    3198
Alloc PE                    3129
Free PE                     69
Total PVG                   0
Total Spare PVs             0
Total Spare PVs in use      0

Use of uninitialized value in concatenation (.) or string at testperl.pl line 13, <> line 2.
sh[2]: Syntax error at line 2 : `|' is not expected.
Argument "--- Volume groups ---\nVG Name                     /dev/..." isn't numeric in multiplication (*) at testperl.pl line 14, <> line 2.
Argument "--- Volume groups ---\nVG Name                     /dev/..." isn't numeric in multiplication (*) at testperl.pl line 14, <> line 2.

Please show example output from vgdisplay vgname and vgdisplay -v, I'll be able to help you better.

I suspect $NF's being substituted when it shouldn't be, in a shell they put that in single quotes for a reason, you may need to escape it like \$NF.

When 3/4 of your code is shell code in backticks and the remaining 25% doesn't use any of perl's advantages, I think it's a sign this problem is better solved in shell... You're not even using perl to measure the length of a string, just echoing it into a shell process...

Thanks for your response..

$ vgdisplay vgesar | grep -i 'Free PE' | awk '{print $NF}'
69

As i said am just starting with perl. this is one block. Am trying to use perl, as i ll have difficulties comparing floating point values in shell script.

I have already tested this with shell script and works fine. but i just want to know why the same unix command gives the same result as executed in a shell script

---------- Post updated at 12:37 AM ---------- Previous update was at 12:35 AM ----------

As requested by you am pasting the vgdisplay $A

$A here is vgesar -> vgdisplay vgesar

$ vgdisplay vgesar
--- Volume groups ---
VG Name                     /dev/vgesar
VG Write Access             read/write
VG Status                   available, exclusive
Max LV                      255
Cur LV                      1
Open LV                     1
Max PV                      100
Cur PV                      2
Act PV                      2
Max PE per PV               1599
VGDA                        4
PE Size (Mbytes)            32
Total PE                    3198
Alloc PE                    3129
Free PE                     69
Total PVG                   0
Total Spare PVs             0
Total Spare PVs in use      0

[edit] think we crossposted. I still need the -v one though!

---------- Post updated at 01:12 PM ---------- Previous update was at 01:09 PM ----------

Because, as already explained, this isn't a shell script, this is shell script inside perl, and things are being substituted inside perl before the shell even gets to it.

You can see the same problem in shell code:

$ NF=slartibartfast
$ echo '{ $NF }'
{ $NF }
$ echo "'{ $NF }'"
{ slartibartfast }
$

If you wanted the literal string $NF, double quotes won't cut it, even if you single quote things inside double quotes.

I'll work on a solution for you. (still need the -v output)

Please find attachment of vgdisplay -v

Also just to add $NF comes with awk utility.

to get the last field

Thank you. That helps a lot, because the output I found on google is very different from the output you have.

I know what awk is. You can do the entire thing in awk. It supports floating point.

---------- Post updated at 02:01 PM ---------- Previous update was at 01:34 PM ----------

#!/bin/sh

printf "Please Enter the VG name to be checked: "
read VOL

printf "Please Enter the free size to be checked in GB: "
read SIZE

vgdisplay "$VOL" 2> /dev/null | awk -v VOL="$VOL" -v SIZE="$SIZE" '
        # Capture the last field of these two lines
        /Free PE/       { FREE=$NF; }
        /PE Size/       { PE=$NF; }
END {   if( (!FREE) || (!PE) )
        {
                print VOL, "does not exist"
                exit
        }

        # Get EXACTLY how many PE is needed.
        NEEDPE=sprintf("%d", ((SIZE*1024)/PE) );
        # .000001 more means we need a whole extra PE.
        if( (SIZE * 1024) - (NEEDPE*PE) > 0) NEEDPE++;

        if(NEEDPE <= FREE)
                printf("%s has enough, %f GB needs %d/%d free PE\n", VOL, SIZE, NEEDPE, FREE);
        else    printf("%s has %d PE, %d more are needed\n", VOL, FREE, NEEDPE-FREE);
}'

Yeah.. thats right.. We can do that in awk too..

But my doubt is simple..

In command line the O/P of the below command is

$ vgdisplay vgesar | grep -i 'Free PE' | awk '{print $NF}'
69

In shell script to assign this O/P to a variable it is

A=vgesar
FREE=`vgdisplay vgesar | grep -i 'Free PE' | awk '{print $NF}'`
echo $FREE

How to get the above O/P assigned to a variable in perl script ??

I've already answered that, twice, and did so before suggesting any other solutions. I have no idea if my suggestion worked or not, and having no way to test it here myself, I must wait for you to do as I asked to find out.

To spell it out keystroke by keystroke:

$FREE = `vgdisplay $A | grep -i 'Free PE' | awk '{print \$NF}'`;

I should note you're running sh 4 separate times, awk twice, and perl once; it's a bit of a stretch to call your script 'perl'. You're also running 14 processes when all you needed was 2. If you really want to do it in perl, you should be processing all the output in perl.