Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Modifying %ENV From The Shebang Line

by williams (Beadle)
on Dec 17, 2007 at 22:20 UTC ( #657530=perlquestion: print w/replies, xml ) Need Help??
williams has asked for the wisdom of the Perl Monks concerning the following question:

I'm writing a Subversion hook script that is expected to run with an empty %ENV. My script needs $LD_LIBRARY_PATH set a particular way before it starts. I've tried every shebang (#!) line I know to try to sneak in an environment variable. Here's a simple try.
#!/usr/bin/env LD_LIBRARY_PATH=/my/lib /usr/bin/perl warn "$ENV{LD_LIBRARY_PATH}\n";
This causes the env process to churn the CPU and to never return. I never see the Perl start. I've tried others as well. Oddly, the following does start the Perl, but doesn't give me the env I need.
#!/usr/bin/env /usr/bin/perl
This, based on perlrun, causes sh to complain that the -- and everything after it is an invalid option.
#!/bin/sh -- # -*- perl -*- eval 'exec /usr/bin/env LD_LIBRARY_PATH=/my/lib /usr/bin/perl -S $0 + ${1+"$@"}' if $runningUnderSomeShell;
This last one fails to find all the DSOs needed by use.
#!/usr/bin/perl BEGIN {$ENV{LD_LIBRARY_PATH}='/my/lib'} use SVN::Core; ...
I can always have a completely different shell script to setup the environment and exec the Perl, but that seems crufty.

I'm on RedHat Linux 4.5, running Perl 5.8.8. Thanks for any help you can provide.


Replies are listed 'Best First'.
Re: Modifying %ENV From The Shebang Line
by ikegami (Pope) on Dec 17, 2007 at 23:39 UTC

    First, what's with env all over the place? Not only is it useless, I think it's actually hurting here. You're asking it to locate the program LD_LIBRARY_PATH=/my/lib.

    Secondly, perlrun doesn't mention
    #!/bin/sh -- -*- perl -*-
    but it does mention
    #!/bin/sh -- # -*- perl -*-
    Unfortunately, that doesn't work with my sh.

    However, it's easy to work around that using -x.

    #!/bin/sh eval 'MYTESTVAR=/my/lib exec /usr/bin/perl -x -S $0 ${1+"$@"}' if $runningUnderSomeShell; #!perl print "[", $ENV{MYTESTVAR}, "]\n";
      Well, that's good enough for the front burner, i.e., that works great! I'll press on with -x.

      You're right about perlrun, though it doesn't matter. My code was right; my post was wrong, and I'll correct it.

      Thanks to all who replied. I've now been made whole by PerlMonks yet again.


Re: Modifying %ENV From The Shebang Line
by philcrow (Priest) on Dec 17, 2007 at 22:27 UTC
    Could you use a dummy script to launch the actual one?
    #!/bin/bash export envar=value /path/to/actual/perl/script
    The Gantry Web Framework Book is now available.
      That was also one of the solutions I posted. It does indeed work, but it seems crufty. For every Perl hook script I write, I've got to write a shell layer to kick it off. The layers could probably be symbolic links to a common script. If that's the best I can do, I can live with it. I just thought there was a better way, given the sneaky shebangs in perlrun.



        One environment-fixing wrapper, as shown, but taking an argument that specifies which perl hook script to be run.
        #!/bin/bash export LD_LIBRARY_PATH=... export HOOKS_PATH=/path/to/svn/hooks [ -f $HOOKS_PATH/$1 ] && perl $HOOKS_PATH/$1

        [ e d @ h a l l e y . c c ]

Re: Modifying %ENV From The Shebang Line
by shmem (Chancellor) on Dec 17, 2007 at 23:39 UTC
    #!/usr/bin/perl unless ($ENV{FOO} =~ /fitzblorf/) { $ENV{FOO} = 'fitzblorf'; exec $0, @ARGV; }


    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      That would need to be wrapped in a BEGIN block since it needs to be executed before a use statement.
        Of course, but that would be advanced usage... if you do such bold stuff as loading modules, it would be required, yes ;-)


        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Modifying %ENV From The Shebang Line
by eserte (Deacon) on Dec 17, 2007 at 22:52 UTC
    I tried the first shebang line on my FreeBSD system, and it also failed. From looking at the truss output, it seems that the system uses execve(2) to call the shebang interpreter. So I looked at the execve manpage and found this paragraph:

         An interpreter file begins with a line of the form:
               #! interpreter arg
         When an interpreter file is execve'd, the system actually execve's the
         specified interpreter.  If the optional arg is specified, it becomes the
         first argument to the interpreter, and the name of the originally
         execve'd file becomes the second argument; otherwise, the name of the
         originally execve'd file becomes the first argument.  The original argu-
         ments are shifted over to become the subsequent arguments.  The zeroth
         argument is set to the specified interpreter.
    Note: it's arg (singular). The manpage claims that this is POSIX standard, so it might apply to Linux, too.
      Maybe that explains some of the results I've seen, where it appears everything after interpreter is glommed into a single argument. I'm now left with attempts like the following, which just churn the CPU and never start Perl.
      #!/bin/bash eval 'LD_LIBRARY_PATH=/my/lib /usr/bin/perl /the/script' if $runningUnderSomeShell; warn "$ENV{LD_LIBRARY_PATH}\n";
      Again, this is based on perlrun, though I'm obviously doing something wrong.



Re: Modifying %ENV From The Shebang Line
by ikegami (Pope) on Dec 17, 2007 at 22:25 UTC
    Why? Why not just use
    #!/usr/bin/perl BEGIN { $ENV{LD_LIBRARY_PATH} = '/my/lib'; } ...
      Because, from the OP's description, perl doesn't load at all without the proper environment variables. So any adjustment to the environemnt must be made before perl starts.
      That was the last of the solutions I posted. I get unresolved references from the use lines of the Subversion modules at startup. Everything works fine when $LD_LIBRARY_PATH includes where those libraries are installed.



Re: Modifying %ENV From The Shebang Line
by graff (Chancellor) on Dec 17, 2007 at 23:01 UTC
    Have you tried (would it be suitable to use) the -I/lib/path option on the perl script's shebang line?
    #!/usr/bin/perl -I/path/containing/my_modules use My::Module; # should load /path/containing/my_modules/My/Module. +pm
    This has always worked for me...

    UPDATE: Sorry, I see that I have misunderstood the question. Having checked the man page for "env", I would have expected the use of LD_LIBRARY_PATH=/some/path to work. Then again, I'm looking at a freebsd man page for this utility, and it looks like its behavior may differ according to your OS (in particular, "env"s behavior changed between freebsd 5.6 and 6.0, for example...) Maybe you need to use "/usr/bin/env -S ..." to get things to work as expected? (Maybe the "-S" option is peculiar to freebsd? I don't know.)

      Subversion starts the hook script, and forces a particular command line syntax that doesn't include Perl's -I. However, I could use the lib pragma to get the same effect, and I am doing that. Somehow, though, it's not enough. I need $LD_LIBRARY_PATH also set before Perl starts or I get either an unresolved reference or a core dump from within the Subversion API.



Re: Modifying %ENV From The Shebang Line
by educated_foo (Vicar) on Dec 17, 2007 at 23:38 UTC
    The "-*- perl -*-" bit is just for Emacs's benefit, so you should try leaving it off (you can always use a local variables section at the end instead).
      That's not true. Perl needs it or else it will run the #! line when it notices "perl" isn't present in it.
        I stand corrected. I had forgotten (or maybe never read) that part. The full details in perlrun are much too long to quote, but here's one relevant passage:
        If the #! line does not contain the word "perl", the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do #!, because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://657530]
Approved by ikegami
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (3)
As of 2018-01-17 21:01 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (206 votes). Check out past polls.