Setting ENV varibles by calling a shell script within a perl program

Discussion in 'Perl Misc' started by ad, May 29, 2004.

  1. ad

    ad Guest

    I need to make some system calls to other programs from a perl program
    and those programs that are being called have some environment
    variable dependencies that are set by a shell script program. So I
    have to call this shell script to set up (export bunch of variables)
    environment variables so that the other program that I call can run
    fine.

    If all possible, I am trying to avoid writing another shell program
    that call the other shell program prior to my perl program since I
    have lots of variable combination that my perl program can run with
    and do not want to have all the variable validated with this extra
    shell program so that it can call my perl program.

    In the following example, I tried both "system" and "``" (backtricks)
    but none of them worked.

    ---- Shell Program ------------
    #!/bin/sh

    export T1=test1
    export T2=test2
    export T3=test3
    export T4=test4
    ---- End Of Shell Program -----

    ----- My Test Perl Program ----
    #!/usr/bin/perl

    use warnings;
    use strict;

    #system(". ./myShell.sh"); # Tried both
    `. ./myShell.sh`;


    print "T1 = $ENV{T1}\n"; # Prints blank
    print "T2 = $ENV{T2}\n"; # Prints blank
    print "T3 = $ENV{T3}\n"; # Prints blank
    print "T4 = $ENV{T4}\n"; # Prints blank
    ----- End Of Perl Program ----

    Thanks for the help and suggestions in advance.
    ad, May 29, 2004
    #1
    1. Advertising

  2. ad <> wrote:
    >
    > I need to make some system calls to other programs from a perl program
    > and those programs that are being called have some environment
    > variable dependencies that are set by a shell script program. So I
    > have to call this shell script to set up (export bunch of variables)

    ^^^^^^^
    > environment variables so that the other program that I call can run
    > fine.



    No you don't.

    You can set env vars in Perl via the %ENV hash.

    Any external processes (child) you start will inherit their env from
    the Perl program (parent).


    > If all possible, I am trying to avoid writing another shell program
    > that call the other shell program prior to my perl program since I
    > have lots of variable combination that my perl program can run with
    > and do not want to have all the variable validated with this extra
    > shell program so that it can call my perl program.



    If you want access to those env vars in your Perl program, then
    wrapping it in a sh program is what you should do.

    I don't think I understand what your objection to that approach is.

    Why is that not a good solution?


    > #system(". ./myShell.sh"); # Tried both



    If you just want to launch programs that make use of those env vars,
    and don't need them in your Perl program, then just set them in
    the same (sub) process:


    system '. ./myShell.sh; other_prog';


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, May 29, 2004
    #2
    1. Advertising

  3. Tad McClellan wrote:

    > ad <> wrote:
    >>
    >> I need to make some system calls to other programs from a perl program
    >> and those programs that are being called have some environment
    >> variable dependencies that are set by a shell script program. So I
    >> have to call this shell script to set up (export bunch of variables)

    > ^^^^^^^
    >> environment variables so that the other program that I call can run
    >> fine.

    >
    >
    > No you don't.


    Sometimes ... you do.

    e.g., I have a program "P" which can be installed anywhere. There is a
    script which may call a script which may call a script that sets
    "P_HOME". That script, or a symlink to it, is in a well-known place,
    even if that is relative to where my perl script is located.

    Much easier, safer, and maintainable would be to have my perl script
    use the shell to interpret the script that sets the environment. This
    way, when the sysadmin moves P to a new location, s/he only must
    maintain a single point of contact (the shell script), which s/he is
    very likely to remember to do, but would be very unlikely to remember
    to update a perl script to have the same ENV entry.

    > You can set env vars in Perl via the %ENV hash.


    Yes - but that's not always useful.

    > Any external processes (child) you start will inherit their env from
    > the Perl program (parent).
    >
    >
    >> If all possible, I am trying to avoid writing another shell program
    >> that call the other shell program prior to my perl program since I
    >> have lots of variable combination that my perl program can run with
    >> and do not want to have all the variable validated with this extra
    >> shell program so that it can call my perl program.

    >
    >
    > If you want access to those env vars in your Perl program, then
    > wrapping it in a sh program is what you should do.
    >
    > I don't think I understand what your objection to that approach is.
    >
    > Why is that not a good solution?


    An extra layer of dependancy? In this world, we have A.sh calling
    A.pl. We then need to ensure that no one calls A.pl except through
    A.sh. This may be trivial for a new program, but if it's an existing
    perl script which is being called by numerous automated processes, that
    may not be as good.

    >> #system(". ./myShell.sh"); # Tried both

    >
    >
    > If you just want to launch programs that make use of those env vars,
    > and don't need them in your Perl program, then just set them in
    > the same (sub) process:
    >
    >
    > system '. ./myShell.sh; other_prog';


    Yes - I think this is the easiest solution that completely fulfills the
    OPs requests. The downside is that if "other_prog" has shell
    metacharacters in the commandline, or anything else the shell may take
    funny, it'll be a blast getting around it.


    Another solution, which is kinda ugly, is to do something like this:

    my @lines = `. myShell.sh; env`;

    Then, parse each line, splitting on '=', and putting them into your
    %ENV hash:

    foreach my $line (@lines)
    {
    /([^=]+)=(.*)/ and $ENV{$1} = $2;
    }

    This may have some funny side effects - if myShell.sh sets some
    variable that Perl ends up using, what happens depends on whether the
    perl module in question has already read that environment variable or
    not.

    Here, then, you can go back to using the multi-arg version of system to
    avoid the shell's reinterpretation of your commands.
    Darin McBride, May 30, 2004
    #3
  4. ad

    Sam Holden Guest

    On Sun, 30 May 2004 00:18:03 GMT,
    Darin McBride <> wrote:
    > Tad McClellan wrote:
    >
    >> ad <> wrote:
    >>>
    >>> I need to make some system calls to other programs from a perl program
    >>> and those programs that are being called have some environment
    >>> variable dependencies that are set by a shell script program. So I
    >>> have to call this shell script to set up (export bunch of variables)
    >>> environment variables so that the other program that I call can run
    >>> fine.


    [snip]

    >>> If all possible, I am trying to avoid writing another shell program
    >>> that call the other shell program prior to my perl program since I
    >>> have lots of variable combination that my perl program can run with
    >>> and do not want to have all the variable validated with this extra
    >>> shell program so that it can call my perl program.

    >>
    >>
    >> If you want access to those env vars in your Perl program, then
    >> wrapping it in a sh program is what you should do.
    >>
    >> I don't think I understand what your objection to that approach is.
    >>
    >> Why is that not a good solution?

    >
    > An extra layer of dependancy? In this world, we have A.sh calling
    > A.pl. We then need to ensure that no one calls A.pl except through
    > A.sh. This may be trivial for a new program, but if it's an existing
    > perl script which is being called by numerous automated processes, that
    > may not be as good.


    I'd do

    ; mv perl_program ORIGperl_program
    ; cat <<HERE >perl_program
    > #!/bin/sh
    > . myShell.sh
    > exec ORIGperl_program
    > HERE

    ; chmod 755 perl_program

    Probably using full paths...

    Unless there are some situations where MyShell.sh should *not* be
    sourced before executing the perl program or sourcing MyShell.sh
    twice should *not* be done then I can't see a problem with that.
    All the automated processes are going to now be calling the shell
    script wrapper.

    If either of those two situations apply then I'd consider that a huge
    bug that needs to be fixed anyway.

    Or modify myShell.sh to also do:

    MYSHELL_HAS_BEEN_RUN=1
    EXPORT MYSHELL_HAS_BEEN_RUN

    and modify the perl program to start with:

    [completely untested, I haven't considered handling the various
    ways a program can be started (and effect on $0)]

    use strict;
    use warnings;
    use FindBin;
    use File::Basename;

    unless ($ENV{MYSHELL_HAS_BEEN_RUN}) {
    exec ". myShell.sh; $FindBin::Bin" . basename($0);
    }

    But that seems error prone.

    --
    Sam Holden
    Sam Holden, May 30, 2004
    #4
  5. ad

    ad Guest


    >> system '. ./myShell.sh; other_prog';

    >

    Thanks for all the replies and information. The above system call helped
    to solve my problem. I didn't think about calling multiple calls in one
    "system" before.

    Thanks everyone again.
    ad, May 30, 2004
    #5
  6. ad

    Uri Guttman Guest

    Re: Setting ENV varibles by calling a shell script within a perlprogram

    >>>>> "DM" == Darin McBride <> writes:


    DM> Another solution, which is kinda ugly, is to do something like this:

    DM> my @lines = `. myShell.sh; env`;

    that is the best way to do it. it isn't ugly, just clumsy.

    DM> Then, parse each line, splitting on '=', and putting them into your
    DM> %ENV hash:

    DM> foreach my $line (@lines)
    DM> {
    DM> /([^=]+)=(.*)/ and $ENV{$1} = $2;
    DM> }

    bah.

    my $env = `. myShell.sh; env`;

    local( %ENV ) = $env =~ m/^([^=]+)=(.+)$/mg ;

    DM> This may have some funny side effects - if myShell.sh sets some
    DM> variable that Perl ends up using, what happens depends on whether the
    DM> perl module in question has already read that environment variable or
    DM> not.

    not if you localize %ENV first. do it in a block and the old %ENV be
    back when you exit the block.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, May 30, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Juggler
    Replies:
    3
    Views:
    17,955
    pradeepreddy3
    Nov 19, 2009
  2. biner
    Replies:
    2
    Views:
    340
    Fredrik Lundh
    Dec 21, 2004
  3. Ankit Mehta
    Replies:
    1
    Views:
    1,391
    Simon Brooke
    Sep 29, 2006
  4. jay
    Replies:
    7
    Views:
    232
    Chad Perrin
    May 3, 2007
  5. moongeegee

    execute a shell script in a shell script

    moongeegee, Dec 3, 2007, in forum: Perl Misc
    Replies:
    2
    Views:
    239
    Ben Morrow
    Dec 4, 2007
Loading...

Share This Page