We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Help in debugging perl code

akatsuki27
akatsuki27 asked
on
Medium Priority
555 Views
Last Modified: 2012-05-11
I have this code snippet that's producing errors:

foreach my $cluster (@clusters){
        open PIPE, "$hi -V $cluster |" or die "pipe open failed: $!";
        my @hosts;
        while (<PIPE>){
                chomp;
                # skip unless line contains type1 or type2
                next unless m{type1|type2};
                # extract the first string (hostname)
                my ($host) = split /\s+/;
                push @hosts, $host;
        }
        close PIPE;
        push @list, @hosts;
}

Open in new window


The error I'm getting is:

Bareword "PIPE" not allowed while "strict subs" in use at collect_du.pl line 39.
Bareword "PIPE" not allowed while "strict subs" in use at collect_du.pl line 49.

If I comment out the 'use strict' pragma which I'd rather not do, then I get this error:

pipe open failed: No such file or directory at ./collect_du.pl line 38.


So basically, the open is failing but I tried different formats like \&PIPE but that didnt work either. I'm not sure how to fix this. Can anyone help?

Any help is appreciated. Thanks.
Comment
Watch Question

Commented:
Could you send the whole file?
Also, which version of perl do you use?
Try

# perl -v

This is perl, v5.10.1 (*) built for i686-cygwin-thread-multi-64int
(with 13 registered patches, see perl -V for more detail)

Copyright 1987-2009, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Author

Commented:
perl -v

This is perl, v5.8.8 built for x86_64-linux-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Commented:
Thanks.
Could you also send the whole script/file since I don't see anything wrong with the snippet you sent?

.

Author

Commented:
This is what I have so far...
#!/usr/bin/perl

use strict;
use warnings;
use lib '/path/to/kerberos/lib/';

use Net::SSH::Perl;
use ITG::Kerberos;
use Sys::Hostname;
use File::Remote qw(:replace);

my $hi = "/path/to/command/bin/hi";
my $user = "akatsuki27";
my @clusters = ("clusterA","clusterB","clusterC","clusterD","clusterE");
my @list;

ITG::Kerberos::init('akatsuki27','/path/to/home/akatsuki27/.keytab') or die 'could not kinit';

#
# Get the list of types 1 and 2
#

foreach my $cluster (@clusters){
        open PIPE, "$hi -V $cluster |" or die "pipe open failed: $!";
        my @hosts;
        while (<PIPE>){
                chomp;
                # skip unless line contains type1or type2
                next unless m{type1 | type2};
                # extract the first string (hostname)
                my ($host) = split /\s+/;
                push @hosts, $host;
        }
        close PIPE;
        push @list, @hosts;
}
@list = sort @list;
# drop last array element which is 'standby' host-- not needed
splice(@list, 54, 1);

#
# Collect the disk usage data from each listed host
#
my $csv = "/path/to/local/csv/file/du_collection.csv";
open (my $csv_fh, '>', $csv) or die "Cannot create <$csv> file $!";

for my $each (@list){
        chomp $each;
        open (my $remote_fh, "$each:/path/to/remote/csv/file/du_out.csv") or
                warn "Cannot open the csv file on $each $!\n" and next;
        <$remote_fh> for (1..3);

        print $csv_fh "*************** $each ***************";

        while (<$remote_fh>){
                print {$csv_fh} $_;
        }
        close $remote_fh;
}
close $csv_fh;

Open in new window

Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview

Author

Commented:
Well it's going to run from cron once it's complete but right now i'm just executing it from the shell.

Let me try the parentheses and post my results.

Commented:
How do you run it from shell command line?

Author

Commented:
Still getting compilation errors after adding the parentheses.

Bareword "PIPE" not allowed while "strict subs" in use at collect_du.pl

Author

Commented:
./collect_du.pl

Commented:
Maybe you can try to add:
     use diagnostics -verbose;
after the use strict; to see what you get.
I can't reproduce the error on my side.

Good luck.

Author

Commented:
This is part of the message I received.

Execution of ./collect_du.pl aborted due to compilation errors (#1)
    (F) With "strict subs" in use, a bareword is only allowed as a
    subroutine identifier, in curly brackets or to the left of the "=>"
    symbol.  Perhaps you need to predeclare a subroutine?

Can you clarify what it means?
CERTIFIED EXPERT

Commented:
Solution, don't use bareword filehandles.

change:
open PIPE, "$hi -V $cluster |" or die "pipe open failed: $!";

Open in new window


to:
open my $pipe, '-|', "$hi -V $cluster" or die "pipe open failed: $!";

Open in new window


and the other related statements will also need to be changed to use the lexical filehandle
CERTIFIED EXPERT

Commented:
I keep forgetting precedence order, so you may need to add the parens.

open (PIPE, "$hi -V $cluster |") or die "pipe open failed: $!";

Open in new window

Author

Commented:
I tried the parentheses and was still getting the bareword error. Then I tried your code below and I got this error:

Bad usage of open(HANDLE, file) at ./collect_du.pl line 39


open my $pipe, '-|', "$hi -V $cluster" or die "pipe open failed: $!";

Open in new window

CERTIFIED EXPERT

Commented:
Try it with the parens
open (my $pipe, '-|', "$hi -V $cluster") or die "pipe open failed: $!";

Open in new window


If that still produces an error, then I'd say that your perl installation is broken.  Since 5.8.8 is considered a little on the old side.  The current release is 5.12.3

Author

Commented:
Yeah I guess it is old then because I'm still seeing the error.

Commented:
I would try another version b/c I'm completely puzzled by that error.

Author

Commented:
I ran the program through the debugger and I got this message:

Bad usage of open(HANDLE, file) at collect_du.pl line 38
 at /usr/lib/perl5/vendor_perl/5.8.8/File/Remote.pm line 331
      File::Remote::open('undef', '-|', '/path/to/command/bin/hi -V clusterA') called at collect_du.pl line 38
Debugged program terminated.  Use q to quit or R to restart,


It seems to be using the File::Remote module to open the local file and since the format is different, I'm getting the "bad usage" error. Is that a correct assessment?

How can I make it distinguish which is local and which is remote?
CERTIFIED EXPERT

Commented:
Hmm,

I forgot you were using File::Remote, which over rides the default open function.

I haven't tested opening a pipe with that module, but a more robust option for the pipe would be to use one of the IPC modules.

IPC::Run - system() and background procs w/ piping, redirs, ptys (Unix, Win32)
http://search.cpan.org/~toddr/IPC-Run-0.89/lib/IPC/Run.pm

IPC::Open2 - open a process for both reading and writing using open2()
http://search.cpan.org/~rjbs/perl-5.12.3/ext/IPC-Open2/lib/IPC/Open2.pm

IPC::Open3 - open a process for reading, writing, and error handling using open3()
http://search.cpan.org/~rjbs/perl-5.12.3/ext/IPC-Open3/lib/IPC/Open3.pm

Author

Commented:
Would it sill override it even if it's inside a subroutine?
CERTIFIED EXPERT
Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview

Author

Commented:
Nice! That cleared up the error on that line.

Unfortunately, I'm now getting an error on the other open lol...which is actually supposed to be correct.

open (my $csv_fh, '>', $csv) or die "Cannot create <$csv> file $!";

Open in new window


Bad usage of open(HANDLE, file) at collect_du3.pl line 60
 at /usr/lib/perl5/vendor_perl/5.8.8/File/Remote.pm line 331
      File::Remote::open('undef', '>', '/path/to/file/du_collection.csv') called at collect_du3.pl line 60
Debugged program terminated.  Use q to quit or R to restart,

Author

Commented:
I increased point value since this turned out to be a long question.
CERTIFIED EXPERT

Commented:
After looking at the source code of the module, it looks like File::Remote doesn't support lexical filehandles, which is really dumb/bad.

Looks like you'll need to revert back to using the bareword 'PIPE' filehandle you originally were using.

Author

Commented:
Sigh...I can't win.

Lexical filehandles I get bad usage errors and barewords I get bareword error:

Bareword "REMOTE" not allowed while "strict subs" in use at collect_du4.pl line 64.
Bareword "REMOTE" not allowed while "strict subs" in use at collect_du4.pl line 73.

I tried using the function-oriented version of File::Remote. This is what the code looks like now:


use File::Remote;

my $remote = new File::Remote;

my $csv = "/path/to/local/file/du_collection.csv";
CORE::open (my $csv_fh, '>', $csv) or die "Cannot create <$csv> file $!";

for my $each (@list){
        chomp $each;
        $remote->open (REMOTE, "$each:/path/to/file/du_out.csv") or warn "Cannot open the csv file on $each $!\n" and next;
        <REMOTE> for (1..3);

        print $csv_fh "*************** $each ***************";

        while (<REMOTE>){
                print {$csv_fh} $_;
        }
        $remote->close (REMOTE);
}
CORE::close $csv_fh;

Open in new window

Author

Commented:
Finally!! Well, not really...

I finally got rid of the stupid bareword error. I found out that if you add * before the bareword then strict pragma is happy again.

I say not really though because the script is not quite working yet...after running it, I get the warning on each remote file:

Cannot open the csv file on host1.foobar.net No such file or directory
 at collect_du4.pl line 64

The thing is, I know for a fact that the file does exist...
$remote->open (*REMOTE, "$each:/path/to/file/du_out.csv") or warn "Cannot open the csv file on $each $!\n" and next;

Open in new window

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.