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

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

Hi fellow monks!

I have a shell script (set_env.sh) which sets some variables. It is usually sourced from other shell scripts.

Now I have a perl script which needs these settings too. So usually I call my script like this:

. ./set_env.sh ./myscript

But I don't like this ;-) One way would be to use a wrapper script containing these 2 commands, but I don't like it too much.

So is there a way to get my script to call set_env.sh and use its settings?

My idea was to do it something like this (incomplete pseudocode) at the very beginning of the code of myscript

#!/usr/bin/perl if ( not defined $ENV{'environment_set'} ) { exec ". ./set_env.sh ; environment_set=1 ./myscript"; } # script follows here

Is there a cleaner way? What do you suggest?


s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

Replies are listed 'Best First'.
Re: How to set (environment) variables for the script
by mr_mischief (Monsignor) on Jun 10, 2010 at 13:48 UTC

    That actually works, but I think it'd be arguably cleaner if you're just setting variables in your shell script to write some Perl to parse the variables out of the script. Currently you're looking at one exec to get the Perl code running. If your environment isn't already set, you're looking at exec'ing another shell, which then reads your shell script for inclusion and execs another perl. It's conceptually pretty simple, but it's going to be tricky to follow in the process tree should you need to do so sometime.

    Compare that to something like this:

    if ( not defined $ENV{'foo'} ) { # foo being some variable already set by your shell # script rather than a separate flag open ( my $se, '<', './set_env.sh' ) or die "Can't read ./set_env.sh : $!\n"; while ( <$se> ) { next unless /(\w+)=["']?(\w+)["']?/; # handling exotic formatting left as an exercise $ENV{$1} = $2; } } print "foo is $ENV{'foo'}!\n";

    If you're running programs from within your shell script to set the environment rather than just setting variables, then I'd stick with what you have. Execing a few more times is a drawback, but it's a tiny one. It would be preferable to additional maintenance if your variable parser got any fancier than the one above.

    I still question the use of a separate flag variable to let you know the environment is set up even when using the shell, but that's more of a personal preference. Other things to consider are whether you have any variables that need to be set prior to perl launching rather than after and whether you're using any of the variables that perl would need to have set as environment variables rather than just reading them into a Perl option hash.

Re: How to set (environment) variables for the script
by walto (Pilgrim) on Jun 10, 2010 at 13:46 UTC
Re: How to set (environment) variables for the script
by Skeeve (Parson) on Jun 10, 2010 at 14:58 UTC

    This gave me the cleanest solution, I guess: perldoc perlrun

    My script starts now like this:

    #!/bin/sh mydir=`dirname $0` . $mydir/set_env.sh exec perl -x $0 "$@" #!perl use strict; use warnings; # and so on...

    Thanks to all who replied!

    Update: In reply to Arge1 below and because I noticed today That I myself needed parameters to my script.

    I appended "$@" to my exec above. This will append all parameters, individually quoted, to the exec command for my perl script to handle them.


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
Re: How to set (environment) variables for the script
by Argel (Prior) on Jun 10, 2010 at 21:49 UTC
    I usually use symlinks and a tcsh script like so:
    lrwxrwxrwx ... inet_audit -> inet_audit.csh* -rwx------ ... inet_audit.csh* -rwx------ ... inet_audit.pl*
    And the contents of inet_audit.csh are below. Note that the $argv:q is used to pass all parameters to the Perl script.
    #!/usr/bin/tcsh source /our/etc/perl5101env_script.csh ./inet_audit.pl $argv:q
    The main I reason I do it this way is so that users, scripts, desktop environments (KDE and GNOME), etc. do not have to be modified if I want to change which script is used. If there were no environment issues then inet_audit would be symlink to inet_audit.pl. This came about after we converted several .sh and .csh scripts to Perl but had to symlink the original names to the new Perl script. UGH!! This also makes it easier to consolidate scripts, simialr to busybox. Anyway, not going to claim it's perfect.

    I do kind of like the exec trick above, but how would I pass parameters in to the Perl script?

    Elda Taluta; Sarks Sark; Ark Arks

      See above for the change. Appending "$@" passes all parameters unchanged to the perl script.


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e