http://www.perlmonks.org?node_id=1034621

ibm1620 has asked for the wisdom of the Perl Monks concerning the following question:

Perl is failing to compile a program of mine that contains the line:
use IPC;
The error message is:
Can't locate IPC.pm in @INC (@INC contains: /home/charrison/bin /usr/ +local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl + /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at + /mxhome/charrison/private/WDI/server/testtom line 26. BEGIN failed--compilation aborted at /mxhome/charrison/private/WDI/ser +ver/testtom line 26.
But the module *is* in @INC - in /home/charrison/bin:
lincoln:/home/charrison/bin$ ll total 12 -rw-r--r-- 1 charrison prod 7065 May 21 15:33 IPC.pm -rwxr-xr-x 1 charrison prod 1382 May 21 15:33 clhtest -rw-rw-r-- 1 charrison charrison 0 Apr 11 14:30 touched
What's unusual about the situation is that the program that exec'ed the Perl program that's failing was launched by xinetd. If I remove 'use IPC;' and put in a few prints, it compiles and I get this output:
Here is env: $VAR1 = { 'REMOTE_HOST' => '::ffff:127.0.0.1', 'PATH' => '/sbin:/usr/sbin:/bin:/usr/bin' }; Here is umask: 2 Here is getpwuid: charrison Just ran touch /mxhome/charrison/testtom_was_here successfully.
So I have no problem writing to my home directory, and there doesn't appear to be anything in IPC.pm's permissions preventing it from being read. What am I missing?

= = = = =

Update 1: I mentioned that am running this from xinetd, but I neglected to mention that, running it from my command line, it works fine.

Replies are listed 'Best First'.
Re: perl unable to locate my module
by LanX (Saint) on May 21, 2013 at 22:26 UTC
    Just a shot in the dark:

    What are the rights of the parentdir /home/charrison/bin (owner, group, modes) and whats the group-id of the process?

    edit

    if for instance the execute-mode is missing for a directory, then you can't access the included files.

    lanx@nc10-ubuntu:/tmp$ echo 1 > dir/tst.pm lanx@nc10-ubuntu:/tmp$ chmod u-x dir lanx@nc10-ubuntu:/tmp$ ll -d dir drw-r-xr-x 2 lanx lanx 4096 2013-05-22 00:28 dir lanx@nc10-ubuntu:/tmp$ perl -Idir -Mtst -e'1' Can't locate tst.pm in @INC (@INC contains: dir /etc/perl /usr/local/l +ib/perl/5.10.0 /usr/local/share/perl/5.10.0 /usr/lib/perl5 /usr/share +/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_pe +rl .). BEGIN failed--compilation aborted.
    but
    lanx@nc10-ubuntu:/tmp$ chmod u+x dir lanx@nc10-ubuntu:/tmp$ perl -Idir -Mtst -e'1'

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      Perms for the parent dir (/home/charrison/bin) are 775, so that should be good. The user/group is charrison/charrison.
        Well, it also fails if earlier dirs in the path have no x mode.

        But if /home/charrison/bin is correct this isn't a likely reason...

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: perl unable to locate my module
by Khen1950fx (Canon) on May 21, 2013 at 22:17 UTC
    Have you tried require?
    #!/usr/bin/perl use strict; use warnings; require '/home/charrison/bin/IPC.pm';
      I got further using 'require'! (Of course, IPC.pm has its own 'use' statement that choked, but I think we're onto something.)

      Will now read up on require.

Re: perl unable to locate my module (errno)
by Anonymous Monk on May 21, 2013 at 22:58 UTC
    To diagnose try
    #!/usr/bin/perl -- open my( $fh ), '/home/charrison/bin/IPC.pm' or die Fudge(); sub Fudge { my @r; while( my($k,$v)=each %!){ $v and push @r, $k } join qq/\n/, int($!).q/ /.$!, int($^E).q/ /.$^E, @r, q/ / } __END__
      No output, which I guess means no error in open?

        No output, which I guess means no error in open?

        Yup, means no error

Re: perl unable to locate my module
by ig (Vicar) on May 22, 2013 at 01:07 UTC

    You might try running your program via strace, either from xinetd or as the user xinetd runs it as. The output from strace should show you what is failing as it searches for the module.

Re: perl unable to locate my module
by eye (Chaplain) on May 22, 2013 at 01:32 UTC
    What are the permissions on "/home/charrison"? Is something like AppArmor or SElinux in use?
Re: perl unable to locate my module
by roboticus (Chancellor) on May 22, 2013 at 13:48 UTC

    CADET

    Update: Never mind.... as LanX messaged me, the error message you received already specified the path. So I'm totally off base.

    How are you getting your bin directory into the @INC path? If you're using the PERL5LIB environment variable, then I'd guess that might be your problem: Code executed from xinetd probably doesn't have the same environment setup as when you're at the command line.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: perl unable to locate my module
by ibm1620 (Hermit) on May 22, 2013 at 23:50 UTC
    Here's where things stand, taking into account various people's suggestions:

    I moved the module to /internal/charrison/. Every directory from root on down is 0777. Still same problems.

    require '/internal/charrison/IPC.pm'; works! (However, it fails when IPC.pm issues 'use WDI;')

    When clhtest (normally invoked by xinetd) is invoked from command line, it works fine, fork/exec'ing 'test'.

    I think I am having some issues with the Perl 'exec' statement (whose documentation I frankly can't fathom). When I write

    $command = q{/usr/bin/perl}; @arglist = q{-I /internal/charrison /internal/charrison/test -l /inter +nal/charrison -P /internal/charrison}; exec $command @arglist;
    It fails in the usual manner. But when I write
    exec "$command @arglist";
    it *does* load IPC.pm successfully -- but then it chokes when IPC.pm does 'use WDI.pm;', like above. At this point I wonder if there's something wrong with the command string I'm passing to exec. (I now realize there are several different ways of giving paramenters to exec(), but I don't understand them, so I should probably stick to the single-argument model.)
      Um, try
      @perl = qw{ /usr/bin/perl -I /internal/charrison }; @program = qw{ /internal/charrison/test }; @args = qw{ -l /internal/charrison -P /internal/charrison }; @cmd = ( @perl, @program, @args ); use Data::Dump; dd( \@cmd ); exec @cmd;
      cause
      [ "/usr/bin/perl", "-I", "/internal/charrison", "/internal/charrison/test", "-l", "/internal/charrison", "-P", "/internal/charrison", ]

      This avoids the shell.

        That seems to have solved the problem. I don't understand how avoiding the shell made any difference, since from what I can make of the exec() doc, involving the shell mainly allows metacharacters to be interpreted.

        However, based on your solution, it appears that the safest way to pass multiple arguments to exec() is in an array of "words" (as defined by qw//).

        Thank you for your help!