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

Hello

I am wondering whether there is any control as to the shell within a system() invocation inside a perl script. More specifically, please look at the following code extract:

#!/bin/ksh . /env.ksh exec $PERL -w -x "$0" "$@" #!perl #line 6 ... system("shellFunction"); ...

The intent is to have the settings of env.ksh available for the invocation of shellFunction, i.e. shellFunction is defined in env.ksh. So far I only see a naked sh as the shell that tries to run shellFunction.

Thanks for the help, Claudius

Replies are listed 'Best First'.
Re: shell within system() call
by almut (Canon) on Mar 19, 2010 at 19:53 UTC

    As system always starts a new shell (or no shell at all, in case the command doesn't contain any shell metacharacters), the only way to make shell functions available is by sourcing the definitions in that new shell.  And in case you need a ksh, you'll also want to start the shell yourself:

    system('/bin/ksh', '-c', '. /env.ksh ; shellFunction');

    Or, in case env.ksh is huge, and you want to avoid re-sourcing it every time, you could open a pipe to the shell, e.g.

    my $pid = open my $shell, "| /bin/ksh" or die "Couldn't start ksh: $!" +; print $shell ". /env.ksh\n"; print $shell "shellFunction\n"; # later print $shell "shellFunction2\n"; # ...

      All correct, but for the record, and since the sourced file is env.ksh - smells like setting up the environment? - one could also, if so inclined, stuff functions into environment variables, since those are propagated:

      qwurx [shmem] ~ > env BLORF='blorf () { echo $* blorf. };' sh -c 'IFS=" "; eval $BLORF; BLORF=""; blorf I say' I say blorf.

      ;-)

      Hi again

      Many thanks to all that posted! Almut's answer was exactly what I needed: the env.ksh is indeed big enough such as to not want to source multiple times, and piping to the open shell child process is just the right thing to do for me.

      This is also because the first shellFunction invoked is an initialization required by all subsequent shellFunctions being called.

      Cheers,

      claudius

Re: shell within system() call
by ikegami (Patriarch) on Mar 19, 2010 at 20:36 UTC

    When system executes a shell — it doesn't always — Perl uses the shell identified by the following:

    $ perl -MConfig -le'print $Config{sh}' /bin/sh

    It may be possible to redefine it when you build Perl or maybe even by changing Config.pm, but that could cause problems. Instead, simply execute the desired shell explicitly (as shown by almut).

    Be sure to use multi-argument form of system. If you do Perl is guaranteed* to avoid launching /bin/sh in addition to the desired shell.

    system('/bin/ksh', '-c', '. /env.ksh ; shellFunction'); # Good system('/bin/ksh -c ". /env.ksh ; shellFunction"'); # Poor

    * — Guarantee void on Windows.