in reply to using "#!/<perlpath>/bin/perl" to exec a shell script?

We faced a similar issue in our local network: we have "project related" binaries (stuff that just doesn't go into /usr/local/bin on all the various machines) and these need to run from a "common path" on different OS's (solaris/sparc vs. freebsd/i386 vs. freebsd/amd64 etc) -- people using a given tool want to use it the same way, no matter which machine they happen to be sitting in front of.

I don't know if this will help for your case, but the method we came up with was something like this:

Setting it up and keeping things straight as new machines are brought online is pretty simple once you get used to it, and maintaining the different binary installations is something we'd have to do in any case -- this arrangement actually makes that part a little easier to manage, I think.

The same basic approach also covers "/common/lib" and a few other things where different versions of files need to be sorted out according to what kind of machine is using them.

  • Comment on Re: using "#!/<perlpath>/bin/perl" to exec a shell script?

Replies are listed 'Best First'.
Re^2: using "#!/<perlpath>/bin/perl" to exec a shell script?
by cadphile (Beadle) on Oct 04, 2007 at 04:14 UTC
    I like this idea. Basically you have the common path, linked through the local machine (and hence machinetype) to another link to the actual perl binary:
    ## common shared automount:
       /<perlpath</bin/perl -> /usr/local/perl588
    ## i386:
       /usr/local/perl588 -> /<perlpath>/i386/bin/perl
    ## sparc:
       /usr/local/perl588 -> /<perlpath>/sparc/bin/perl
    
    This would work if I could get our admin team to add these links by default in the standard setup of our servers. We have *thousands* of sparc servers however, running both Solaris9, and Solaris10, and about a hundred so far of the i386 servers. Unfortunately I can't modify the standard unix file structures.

    The basic mystery here is how to trick the unix kernel into thinking that a shell script is a legitimate binary file that returns the appropriate "magic number". The "magic number" apparently is an evaluation of the first two bytes in the file. Hence if the first two bytes of a file are #!, the file is a shell script; if they're %!, it's a postscript file, etc. Files that are "exec"-able from the kernel have "0x75" "E" "L" "F" as the first four characters.

    The more I discuss this, the more I'm convinced it's not possible to do what I'm trying to do. The real solution appears to be to just change all our scripts once, to invoke perl using

       #!/bin/sh -- # -*- perl -*-
       eval 'exec <perlpath>/bin/perl -S $0 ${1+"$@"}'
         if 0;
    
    This solution is actually relevant now that we really can't rely on the #! direct reference to the interpreter.

    But if there's some really really deep dark ancient magic that can work here, I am your humble adept...

      There may be another way:
      #!/usr/bin/env perl
      That is not ideal. It still involves updating all those scripts (but at least the update is a simple and constant string replacment). It puts the load on managing how the PATH, PERLLIB, PERL5LIB (and other?) shell variables are set for every user at every machine (but you might need at most half a dozen distinct settings, depending on how many distinct perl builds are needed).

      And of course, whenever you bring in a script that some else has written (e.g., as posted at PerlMonks), you'll probably need to edit the shebang line -- but I gather you might be doing this already.