perl compilation: 'Too many levels of symbolic links' - perl

In Linux, installation of perl is failing while running make test command
t/op/exec ...................................................... # Failed test 17 - at op/exec.t line 114
# $! eq 40, 'Too many levels of symbolic links'
FAILED at test 17
Error is not indicating for which symbolic link it is failing.
Steps Followed:
- Download perl archive from https://www.cpan.org/src/
- [user#hostname perl-5.28.3]$ tar -xvzf perl-5.28.3.tar.gz
- [user#hostname perl-5.28.3]$ cd perl-5.28.3
- [user#hostname perl-5.28.3]$ ./Configure -des -Dinstallprefix=<installation directory>
- [user#hostname perl-5.28.3]$ make
- [user#hostname perl-5.28.3]$ make test
Failed 2 tests out of 2464, 99.92% okay.
../cpan/Time-Local/t/Local.t
op/exec.t
Elapsed: 1317 sec
u=12.87 s=34.02 cu=548.85 cs=488.76 scripts=2464 tests=1158447
make: *** [test] Error 1
[user#hostname perl-5.28.3]$ t/TEST op/exec.t
t/op/exec ... # Failed test 17 - at op/exec.t line 114
# $! eq 40, 'Too many levels of symbolic links'
FAILED at test 17
Failed 1 test out of 1, 0.00% okay.
op/exec.t
Verified same behavior is happening for other perl version also, this is indicating some issue with my installation environment.
Any pointer can be helpful.

Thank you for the pointer #choroba.
Following was the root cause.
In <perl-5.28.3>/t/op/exec.t file, we find the following around line 114:
$rc = system { "lskdfj" } "lskdfj";
unless( ok($rc == 255 << 8 or $rc == -1 or $rc == 256 or $rc == 512) ) {
print "# \$rc == $rc\n";
}
unless ( ok( $! == 2 or $! =~ /\bno\b.*\bfile/i or
$! == 13 or $! =~ /permission denied/i or
$! == 22 or $! =~ /invalid argument/i ) ) {
diag sprintf "\$! eq %d, '%s'\n", $!, $!;
}
In my environment PATH env variable value was
[user#hostname perl-5.28.3]$ echo $PATH
/bin:/usr/lib64/qt-3.3/bin:/bin:/usr/bin:/usr/dev_infra/platform/bin:/usr/dev_infra/generic/bin:/usr/local/bin:/usr/local/ade/bin
Within this PATH, for following paths ls attempt is throwing error 'Too many levels of symbolic links'
[user#hostname perl-5.28.3]$ ls -i /usr/local/bin /usr/local/ade/bin
ls: cannot access /usr/local/bin: Too many levels of symbolic links
ls: cannot access /usr/local/ade/bin: Too many levels of symbolic links
[user#hostname perl-5.28.3]$ ls -ltr /usr/local
lrwxrwxrwx. 1 root root 20 Mar 30 2017 bin -> ./packages/local/bin
lrwxrwxrwx. 1 root root 18 Mar 30 2017 ade -> /usr/local/nde/ade
After removing offending paths from PATH, make test is running successfully
[user#hostname perl-5.28.3]$ export PATH=/bin:/usr/lib64/qt-3.3/bin:/bin:/usr/bin:/usr/dev_infra/platform/bin:/usr/dev_infra/generic/bin
[user#hostname perl-5.28.3]$ make test
All tests successful.
Elapsed: 1611 sec
u=14.47 s=44.63 cu=731.82 cs=575.84 scripts=2474 tests=1209537

Related

Why does Perl file test operator "-l" not detect symlinks?

Why does the Perl file test operator "-l" fail to detect symlinks under the following conditions?
System Info
john#testbed-LT:/temp2/test$ uname -a
Linux Apophis-LT 4.13.0-37-generic #42-Ubuntu SMP Wed Mar 7 14:13:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
john#testbed-LT:/temp2/test$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 17.10
Release: 17.10
Codename: artful
Perl Info
john#testbed-LT:/temp2/test$ perl -v
This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux-gnu-thread-multi (with 56 registered patches, see perl -V for more detail)
Test Resources
john#testbed-LT:/temp2/test$ touch regular_file
john#testbed-LT:/temp2/test$ mkdir dir
john#testbed-LT:/temp2/test$ ln -s regular_file symlink
john#testbed-LT:/temp2/test$ ls -al
total 12
drwxrwxr-x 3 john john 4096 May 6 02:29 .
drwxrwxrwx 6 john john 4096 May 6 02:29 ..
drwxrwxr-x 2 john john 4096 May 6 02:29 dir
-rw-rw-r-- 1 john john 0 May 6 02:29 regular_file
lrwxrwxrwx 1 john john 12 May 6 02:29 symlink -> regular_file
Script Containing Failing "-l" Operator
john#testbed-LT:/temp2/test$ cat ~/.scripts/test.pl
#!/usr/bin/perl
use strict;
use warnings;
use Cwd 'abs_path';
my $targetDir = "/temp2/test";
opendir(DIR, $targetDir) || die "Can't open $targetDir: $!";
while (readdir DIR) {
my $file = "$_";
if($file =~ m/^\.{1,2}/) {
next;
}
$file = abs_path($file);
if(-l "$file") {
print "Link: $file\n";
}
elsif(-d "$file") {
print "Dir: $file\n";
}
elsif(-f "$file") {
print "File: $file\n";
}
else {
print "\n\n *** Unhandled file type for file [$file]!\n\n";
exit 1;
}
}
closedir(DIR);
Script Output
john#testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
File: /temp2/test/regular_file
Dir: /temp2/test/dir
File: /temp2/test/regular_file
Problem I'm Trying to Solve
Note in the above output that the symlink (named "symlink") is not listed while the file, "regular_file," is listed twice (I want "symlink" listed -- the actual link and not the file it points to).
When I change ... if(-l "$file") ... to ... if(lstat "$file") ... in the script, again "symlink" is not listed while "regular_file" is listed twice, but they are being listed from within the block meant to catch symlinks, i.e.:
john#testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
Link: /temp2/test/regular_file
Link: /temp2/test/dir
Link: /temp2/test/regular_file
Goal
The output I'm trying to achieve (which is faked below -- not actually generated by the script, but by hand) is:
john#testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
File: /temp2/test/regular_file
Dir: /temp2/test/dir
Link: /temp2/test/symlink
...but not necessarily in that order (I don't care about the order of the listing).
Why is the above-shown script not achieving the above-stated goal (why is the "-l" operator not working)?
perldoc Cwd:
abs_path
my $abs_path = abs_path($file);
Uses the same algorithm as getcwd(). Symbolic links and relative-path components ("." and "..") are resolved to return the canonical pathname, just like realpath(3). On error returns undef, with $! set to indicate the error.
(Emphasis mine.)
If you want to see symlinks, don't use abs_path.
What you want to do instead is
$file = "$targetDir/$file";
i.e. prepend the name of the directory you read $file from.
Additional notes:
opendir(DIR, $targetDir) || die "Can't open $targetDir: $!";
while (readdir DIR) {
my $file = "$_";
should be
opendir(my $dh, $targetDir) || die "Can't open $targetDir: $!";
while (my $file = readdir $dh) {
Why use bareword filehandles when you can just use normal variables (that are scoped properly)?
There's no reason to quote "$_" here.
Why first assign to $_ when you're just going to copy the string to $file in the next step?
Note in the above output that the symlink (named "symlink") is not listed while the file, "regular_file," is listed twice
Yeah, because you used abs_path to turn symlink into /temp2/test/regular_file. Get rid of that line.
By the way, you are missing
$file = "$targetDir/$file";
The only reason your program worked without it is because $targetDir happened to be the current work directory.

cpan2rpm cant stat /tmp folder

Im trying to build perl-Heap-Priority for RHEL6. Weired thing is when I run
cpan2rpm Heap::Priority it shows following
...
Tarball extraction: [/root/rpm/SOURCES/Heap-Priority-0.01.tar.gz]
Can't stat /tmp/CldQkErG6r/18:51: No such file or directory
at /usr/bin/cpan2rpm line 392
get_meta(): No such file or directory at /usr/bin/cpan2rpm line 396.
...
Practically this temporary folder is not created. Buy why?
my tmp folder permission is 777
drwxrwxrwt. 3 root root 4096 May 29 16:35 tmp
Known problem, see https://rt.cpan.org/Ticket/Display.html?id=72421. The problem is the space in the user column of the output.
$ tar -tzvf $HOME/rpmbuild/SOURCES/Heap-Priority-0.01.tar.gz |head -1
drwxr-xr-x James Freeman/544 0 2002-05-07 14:51 Heap-Priority-0.01/
Apply the following patch to fix the problem for this module. To get the name, instead of accessing the fifth column, we're accessing the last one. I do not know what else this patch might break, but it should be less wrong than the original code on average.
diff --git a/cpan2rpm b/cpan2rpm
index 28e8b01..6a36b68 100755
--- a/cpan2rpm
+++ b/cpan2rpm
## -1259,7 +1259,7 ## sub untar($) {
;
chomp($_ = qx/$cmd/);
- $_ = (split)[5] unless $zip;
+ $_ = (split)[-1] unless $zip;
$dst .= "/$1" if m|^(\S+)/?|;
$dst =~ s|/*$||; # path shouldn't end in / or tardir gets wiped
$dst =~ s|\./||; # paths in tarballs shouldn't be relative
You could have found out all of this by yourself by using the debugger. Learn to use this tool, it is invaluable.
I think this might be a sightly cleaner way to do it:
--- /usr/bin/cpan2rpm.orig 2017-10-20 14:45:57.000000000 -0700
+++ /usr/bin/cpan2rpm 2017-10-23 12:29:07.006118950 -0700
## -1258,7 +1258,7 ##
my $cmd = $zip
? "unzip -l $_ | grep -P -o '\\S+/\$' |tail -1"
- : "tar -t${z}vf $_ |head -1"
+ : "tar --numeric-owner -t${z}vf $_ |head -1"
;
chomp($_ = qx/$cmd/);

What goes under the hood of `mkvirtualenv` command?

I am curious about what happens under the hood of the mkvirtualenv command and so I am trying to understand how it calls virtualenv.
The lowest hanging fruit is to figure where the virtualenv program is located after installation and where the mkvirtualenv program is located after installation. So:-
Calvins-MacBook-Pro.local ttys006 Mon Apr 23 12:31:07 |~|
calvin$ which mkvirtualenv
Calvins-MacBook-Pro.local ttys006 Mon Apr 23 12:31:10 |~|
calvin$ which virtualenv
/opt/local/library/Frameworks/Python.framework/Versions/2.7/bin/virtualenv
So the strange thing I see here is that which mkvirtualenv does not give any result. Why?
Digging further, in the virtualenvwrapper directory after installing it, I see only 3 python files:-
Calvins-MacBook-Pro.local ttys004 Mon Apr 23 12:28:05 |/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/virtualenvwrapper|
calvin$ ls -la
total 88
drwxr-xr-x 8 root wheel 272 Apr 13 15:07 .
drwxr-xr-x 29 root wheel 986 Apr 15 00:55 ..
-rw-r--r-- 1 root wheel 5292 Apr 13 15:05 hook_loader.py
-rw-r--r-- 1 root wheel 4810 Apr 13 15:07 hook_loader.pyc
-rw-r--r-- 1 root wheel 1390 Apr 13 15:05 project.py
-rw-r--r-- 1 root wheel 2615 Apr 13 15:07 project.pyc
-rw-r--r-- 1 root wheel 7381 Apr 13 15:05 user_scripts.py
-rw-r--r-- 1 root wheel 11472 Apr 13 15:07 user_scripts.pyc
And I suppose that the only reason why mkvirtualenv is now available in my terminal is because I have added in a source/opt/local/library/Frameworks/Python.framework/Versions/2.7/bin/virtualenvwrapper.sh. So answering the question I asked earlier, this is simply because mkvirtualenv is expressed as a bash function and is available in my terminal because I have sourced virtualenvwrapper.sh in my .bashrc or .bash_profile files.
Digging into the virtualenvwrapper.sh script, I see
# Create a new environment, in the WORKON_HOME.
#
# Usage: mkvirtualenv [options] ENVNAME
# (where the options are passed directly to virtualenv)
#
function mkvirtualenv {
typeset -a in_args
typeset -a out_args
typeset -i i
typeset tst
typeset a
typeset envname
typeset requirements
typeset packages
in_args=( "$#" )
if [ -n "$ZSH_VERSION" ]
then
i=1
tst="-le"
else
i=0
tst="-lt"
fi
while [ $i $tst $# ]
do
a="${in_args[$i]}"
# echo "arg $i : $a"
case "$a" in
-a)
i=$(( $i + 1 ));
project="${in_args[$i]}";;
-h)
mkvirtualenv_help;
return;;
-i)
i=$(( $i + 1 ));
packages="$packages ${in_args[$i]}";;
-r)
i=$(( $i + 1 ));
requirements="${in_args[$i]}";;
*)
if [ ${#out_args} -gt 0 ]
then
out_args=( "${out_args[#]-}" "$a" )
else
out_args=( "$a" )
fi;;
esac
i=$(( $i + 1 ))
done
set -- "${out_args[#]}"
eval "envname=\$$#"
virtualenvwrapper_verify_workon_home || return 1
virtualenvwrapper_verify_virtualenv || return 1
(
[ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT
\cd "$WORKON_HOME" &&
"$VIRTUALENVWRAPPER_VIRTUALENV" $VIRTUALENVWRAPPER_VIRTUALENV_ARGS "$#" &&
[ -d "$WORKON_HOME/$envname" ] && \
virtualenvwrapper_run_hook "pre_mkvirtualenv" "$envname"
)
typeset RC=$?
[ $RC -ne 0 ] && return $RC
# If they passed a help option or got an error from virtualenv,
# the environment won't exist. Use that to tell whether
# we should switch to the environment and run the hook.
[ ! -d "$WORKON_HOME/$envname" ] && return 0
# If they gave us a project directory, set it up now
# so the activate hooks can find it.
if [ ! -z "$project" ]
then
setvirtualenvproject "$WORKON_HOME/$envname" "$project"
fi
# Now activate the new environment
workon "$envname"
if [ ! -z "$requirements" ]
then
pip install -r "$requirements"
fi
for a in $packages
do
pip install $a
done
virtualenvwrapper_run_hook "post_mkvirtualenv"
}
Here's where I don't understand yet - I don't seem to see any direct reference to virtualenv in this bash function. So how exactly does this bash function mkvirtualenv pass the arguments from command line (e.g. mkvirtualenv -p python2.7 --no-site-packages mynewproject) to the python virtualenv program?
So this is the line that does the trick.
(
[ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT
\cd "$WORKON_HOME" &&
"$VIRTUALENVWRAPPER_VIRTUALENV" $VIRTUALENVWRAPPER_VIRTUALENV_ARGS "$#" &&
[ -d "$WORKON_HOME/$envname" ] && \
virtualenvwrapper_run_hook "pre_mkvirtualenv" "$envname"
)
$VIRTUALENVWRAPPER_VIRTUALENV is in fact the location of where the current virtualenv program resides.
In terminal,
Calvins-MacBook-Pro.local ttys004 Mon Apr 23 13:24:14 |~|
calvin$ which $VIRTUALENVWRAPPER_VIRTUALENV
/opt/local/library/Frameworks/Python.framework/Versions/2.7/bin/virtualenv
Mytsery solved.

Perl Cygwin fun. Module is loaded, but not being found by the program

Okay a few rules:
No, I cannot install Strawberry Perl on this system. I have to use Cygwin.
This is Perl 5.8.7. I cannot update it.
This is not my system. This is a customer's system, and I cannot modify it to my hearts content.
Now, we've gotten that out of the way...
I have installed Spreadsheet::Read, Spreadsheet::ParseExcel, and Spreadsheet::XLSX on this system. This installed a little Perl script called xlscat. We've done this before on a development box and the UAT box. Now this is the production box.
I am getting the following error:
Parser for XLSX is not installed at /usr/bin/xlscat line 185
I've traced this to Spreadsheet::Read. The relevant code is:
my #parsers = (
[ csv => "Text::CSV_XS" ],
[ csv => "Text::CSV_PP" ], # Version 1.05 and up
[ csv => "Text::CSV" ], # Version 1.00 and up
[ ods => "Spreadsheet::ReadSXC" ],
[ sxc => "Spreadsheet::ReadSXC" ],
[ xls => "Spreadsheet::ParseExcel" ],
[ xlsx => "Spreadsheet::XLSX" ],
[ prl => "Spreadsheet::Perl" ],
# Helper modules
[ ios => "IO::Scalar" ],
);
my %can = map { $_->[0] => 0 } #parsers;
for (#parsers) {
my ($flag, $mod) = #$_;
print STDERR qq(DEBUG: Flag = "$flag" Mod = "$mod"\n);
$can{$flag} and next;
eval "require $mod; \$can{\$flag} = '$mod'";
}
print STDERR Dumper(\%can); #DEBUG:
The lines that start contain the string DEBUG: are mine.
A dump of #parsers shows that everything is loaded correctly. The first debug prints out the value of $flag and $mod correctly.
The problem seems to come from the eval statement. From what I can see, it runs require against a module, and then sets the $can{$flag} variable to $mod if the require succeeds. Apparently, require Spreadsheet::XLSX fails. Here's the relevant output from my debug statements:
DEBUG: Flag = "csv" Mod = "Text::CSV_XS"
DEBUG: Flag = "csv" Mod = "Text::CSV_PP"
DEBUG: Flag = "csv" Mod = "Text::CSV"
DEBUG: Flag = "ods" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "sxc" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "xls" Mod = "Spreadsheet::ParseExcel"
DEBUG: Flag = "xlsx" Mod = "Spreadsheet::XLSX"
DEBUG: Flag = "prl" Mod = "Spreadsheet::Perl"
DEBUG: Flag = "ios" Mod = "IO::Scalar"
$VAR1 = {
'csv' => 'Text::CSV_XS',
'sxc' => 0,
'xlsx' => 0,
'xls' => 'Spreadsheet::ParseExcel',
'ios' => 'IO::Scalar',
'prl' => 0,
'ods' => 0
};
Hmmm... Maybe the module isn't installed?
$ perldoc -l Spreadsheet::XLSX
/usr/lib/perl5/site_perl/5.8/Spreadsheet/XLSX.pm
It shows up in perldoc. Let's write a quick test program:
#! /usr/bin/env perl
use Spreadsheet::Read;
use Spreadsheet::XLSX;
print "It works\n";
And...
$ ./test.pl
DEBUG: Flag = "csv" Mod = "Text::CSV_XS"
DEBUG: Flag = "csv" Mod = "Text::CSV_PP"
DEBUG: Flag = "csv" Mod = "Text::CSV"
DEBUG: Flag = "ods" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "sxc" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "xls" Mod = "Spreadsheet::ParseExcel"
DEBUG: Flag = "xlsx" Mod = "Spreadsheet::XLSX"
DEBUG: Flag = "prl" Mod = "Spreadsheet::Perl"
DEBUG: Flag = "ios" Mod = "IO::Scalar"
$VAR1 = {
'csv' => 'Text::CSV_XS',
'sxc' => 0,
'xlsx' => 0,
'xls' => 'Spreadsheet::ParseExcel',
'ios' => 'IO::Scalar',
'prl' => 0,
'ods' => 0
};
It works
I can pick up Spreadsheet::XLSX via the use Spreadsheet::XLSX in my test program, yet the require in Spreadsheet::Read doesn't seem to see it.
Why?
Addendum
What do you get if you print Dumper( \%INC ) ? – friedo 2 mins ago
I actually did one better. I added the following line in the loop:
require $mod if ($mod eq "Spreadsheet::XLSX"); #DEBUG
And that produced the error message:
Can't locate Spreadsheet::XLSX in #INC (#INC contains:
/usr/lib/perl5/5.8/cygwin /usr/lib/perl5/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8 .) at
/usr/lib/perl5/site_perl/5.8/Spreadsheet/Read.pm line 57.
Compilation failed in require at ./test.pl line 3.
BEGIN failed--compilation aborted at ./test.pl line 3.
(NOTE: I reformatted the output, so it wouldn't be 1000+ characters long, and it's easier to see the #INC path).
The module is in /usr/lib/perl5/site_perl/5.8/Spreadsheet/XLSX.pm.
Oh, take a look at this too:
$ pwd
/usr/lib/perl5/site_perl/5.8/Spreadsheet
$ ls -la
total 152
drwxr-xr-x+ 4 phalder Domain Users 0 Nov 1 21:51 .
drwxrwxrw-+ 11 twinborne Users 0 Nov 1 22:28 ..
drwxr-xr-x+ 3 phalder Domain Users 0 Nov 1 20:48 ParseExcel
-rwxr-xr-x 1 phalder Domain Users 107773 Apr 6 2011 ParseExcel.pm
-rwxrwxrwx 1 phalder Domain Users 29142 Nov 2 12:53 Read.pm
drwxr-xr-x+ 2 phalder Domain Users 0 Nov 1 21:51 XLSX
-rwxr-xr-x 1 phalder Domain Users 8411 May 16 2010 XLSX.pm
$ ls -la XLSX
total 48
drwxr-xr-x+ 2 phalder Domain Users 0 Nov 1 21:51 .
drwxr-xr-x+ 4 phalder Domain Users 0 Nov 1 21:51 ..
-rwxr-xr-x 1 phalder Domain Users 5487 May 16 2010 Fmt2007.pm
-rwxr-xr-x 1 phalder Domain Users 37046 May 16 2010 Utility2007.pm
The permissions seem okay.
Another Addendum:
When I did a CPAN reinstall, I got this:
Result: PASS
/usr/bin/make test -- OK
Running make install
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ERROR: Can't create '/usr/lib/perl5/site_perl/5.8/cygwin/auto/Spreadsheet/Read'
Do not have write permissions on
'/usr/lib/perl5/site_perl/5.8/cygwin/auto/Spreadsheet/Read'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
at -e line 1
Installing /usr/lib/perl5/site_perl/5.8/Spreadsheet/Read.pm
Installing /usr/share/man/man3/Spreadsheet.Read.3pm
make: *** [pure_site_install] Error 255
/usr/bin/make install -- NOT OK
Oops! I didn't check the permission of the /usr/lib/perl5/site_perl/5.8/cygwin directory tree.
Did a chmod -R a+rx * on the whole /usr/lib/perl5 directory. We'll see if it works again.
Found the Problem
I took a slightly different tact. I modified Spreadsheet::Read to print out $# after the eval. That way, I could see what error it was getting. Here's the results:
$ ./test.pl
DEBUG: ""DEBUG: "Can't locate Spreadsheet/ReadSXC.pm in #INC
(#INC contains:
/usr/lib/perl5/5.8/cygwin
/usr/lib/perl5/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8 .) at (eval 8) line 1.
"DEBUG: "Can't locate Spreadsheet/ReadSXC.pm in #INC
(#INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 9) line 1.
"DEBUG: ""DEBUG: "Can't locate Compress/Raw/Zlib.pm in #INC
(#INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 15) line 1.
"DEBUG: "Can't locate Spreadsheet/Perl.pm in #INC
(#INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 18) line 1.
Did you see that? The problem isn't Spreadsheet::XLSX, but Compress::Raw::Zlib. I set the entire permissions on /usr/lib/perl to 777, and then installed Compress::Raw::Zlib and Spreadsheet::ReadSXC.
This must have been a problem when these modules were initially installed. I wasn't the one doing the cpan install, but helping the person over the phone, so I didn't get a chance to see these errors if they popped up. CPAN tends to be really, really noisy, and I've learned to catch the random error message as CPAN runs by.
The problem may have been /usr/lib/perl5/site_perl/5.8/cygwin not having the correct permissions all along.
The program now works.
Thanks for all of your help. Somehow, it lead me down the right trail.

errorlevel in perl

I need to terminate the perl script according to the return code from the previous step.
something like
IF ERRORLEVEL 1 goto ERROR
in batch processing.
i have
$PROG = `spu_comp 2>&1 $a 1 1`;
i need if this step gives error, program should terminate.
thanks in advance for your inputs.
Immediately after the line where you assign to $PROG, add this line:
($? >> 8) and die "spu_comp exited with non-zero return value";
$ perl -le'`sh -c "exit 0"`;($?>>8) and die "exited with non-zero: ", ($?>>8)'
$ perl -le'`sh -c "exit 1"`;($?>>8) and die "exited with non-zero: ", ($?>>8)'
exited with non-zero: 1 at -e line 1.
It appears that ERRORLEVEL is not a true exit code to perl.
i have the same issue. A bat file of
#Echo OFF
echo setting error level 1
EXIT /B 1
With a perl file of
#!/usr/bin/perl
$command = `C:\foo.bat`;
print "Error Level: " .$? ."\n";
print "Command: " . $command . "\n";
Yields output of
Error Level: 0
Command:
A perl file of
#!/usr/bin/perl
my $command = `dir`;#try both dir and dri to test real exit codes against batch exit codes
print "Error Level: " .$? ."\n";
print "Command: " . $command . "\n";
will yield
C:\>back.pl
'dri' is not recognized as an internal or external command,
operable program or batch file.
Error Level: 256
Command:
C:\>back.pl
Error Level: 0
Command: Volume in drive C has no label.
Volume Serial Number is 8068-BE74
Directory of C:\
12/13/2010 11:02 AM 7 8
06/02/2010 01:13 PM 0 AUTOEXEC.BAT
06/04/2010 01:00 PM <DIR> AutoSGN
12/13/2010 12:03 PM 111 back.pl
06/02/2010 01:13 PM 0 CONFIG.SYS
06/03/2010 07:37 PM <DIR> Documents and Settings
12/13/2010 12:01 PM 46 foo.bat
06/04/2010 03:17 PM <DIR> HorizonTemp
06/02/2010 02:41 PM <DIR> Intel
06/04/2010 02:19 PM <DIR> league
06/04/2010 12:31 PM <DIR> Perl
12/10/2010 03:28 PM <DIR> Program Files
12/08/2010 04:13 PM <DIR> Quarantine
12/13/2010 08:14 AM <DIR> WINDOWS
5 File(s) 164 bytes
9 Dir(s) 18,949,783,552 bytes free
C:\>
You can get the correct return code from $PROG by adding the following line.
my $ret = $?/256 #/
or a cleaner way
my $ret = $? >> 8;
Then compare the $ret with the possible values you can retrieve
if ($ret == 0)
{
# Do something if finished successfully
}
elsif($ret == 1)
{
error();
}
else
{
# Return something else that was nor 0 nor 1
}
Further to #husker's answer, it's worth noting $? only works for codes of 255 or less. Windows error codes typically exceed this. The IPC::System::Simple module, however, provides methods like capture() that can correctly retrieve codes > 255.
e.g.
use Test::More;
use IPC::System::Simple qw(capture $EXITVAL EXIT_ANY);
my $modeTest = capture(EXIT_ANY, "some command that sets error code 5020");
is( $EXITVAL , 5020, "Expect error code 5020" );