Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Creating bash functions using perls $ENV interface

by tid (Beadle)
on Oct 29, 2003 at 02:51 UTC ( [id://302896]=perlquestion: print w/replies, xml ) Need Help??

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

Hello fellow monks,

Quick description: in bash, you can write functions to help with larger scripts, and these are stored in the bash environment somehow (ie they can persist between scripts if "source" is used). How do I set up those functions in the environment from Perl?

Long version: I'm trying to create a stop-gap perl script for automating the build process at the company I work for. The existing build script is done in a pair of bash shell scripts, called from cygwin under windows. I'm running Perl 5.8.0 (Win32 installer version).

The existing build scripts use a two step approach. The first script is designed to be used as a .bash_profile script, or "source"'d in order to import the environment variable definitions into the shell environment. It also defines a few (*cough* evil *cough*) bash script functions that then become available to subsequent scripts called in the same shell.

The second script is the top level script that traverses the source directory tree and builds each of the modules in turn. It extensively uses the bash functions defined by the first script. I'd rather not rework every lower level build script just now (at least until I can rewrite the whole sorry mess).

The big problem is that in order to invoke a shell script, I have to call the interpreter directly. As two separate scripts, this means that they are executed in separate subshells, meaning the environment variables defined in the first script don't carry over.

I can replicate the environment variables using perls $ENV{} facility, but is it possible to use that same interface to add bash function definitions to the environment as well? This would allow me to dispense with the first script entirely, and just call the actual build script.

Many thanks in advance for any perl wisdom provided!
Mike

  • Comment on Creating bash functions using perls $ENV interface

Replies are listed 'Best First'.
Re: Creating bash functions using perls $ENV interface
by sauoq (Abbot) on Oct 29, 2003 at 03:11 UTC

    Update: Actually....

    perl -le '$ENV{sauoq}="() { echo sauoq; }"; print `bash -c sauoq`'
    :-) (And suddenly it occurred to me that export -f had to work somehow.)


    The following was my original reply. When I updated this node after finding a Real Answer™ for the OP, I struck this out. The suggestions below aren't wrong though and someone may still find them useful; so I'm unstriking them.

    As far as I know, there's no way to do exactly what you are asking for. Every process has an environment, and yes, perl gives you access to its with %ENV; but not every process has bash functions... if you see what I mean.

    There are ways you might be able to get around it. You can call your perl script from a bash script which itself declares and exports the function you want available to the shells started from your perl script. Something like this:

    #!/bin/bash sub sauoq() { echo sauoq } export -f sauoq ./script.pl
    and in script.pl:
    #!/usr/bin/perl print `bash -c sauoq`

    Or, you might try opening a pipe to a bash process, writing the functions out to that pipe and keeping it open to run your other scripts.

    -sauoq
    "My two cents aren't worth a dime.";
    

      Heya sauoq,

      Thanks for taking the time to check it out. I just had to delete a whole bunch of response text, as I finally got it to work under cygwin using the following script:

      #!perl -w $CYGWIN_BIN="C:\\cygwin\\bin"; $ENV{TEST_FUNC} = "() {\necho Hey, it works!;\n };\n"; system(("$CYGWIN_BIN\\bash.exe", "-c \"declare -f\"")); system(("$CYGWIN_BIN\\bash.exe", "-c \"TEST_FUNC\""));

      Initially, using your
      perl -le '$ENV{sauoq}="() { echo sauoq; }"; print `bash -c sauoq`'
      I had problems where bash didn't understand what sauoq was. However, the script above does the trick

      Thanks to everyone for the interest guys (especially sauoq) - you guys saved my butt!
      Mike

Re: Creating bash functions using perls $ENV interface
by graff (Chancellor) on Oct 29, 2003 at 05:03 UTC
    If you would like to invoke two separate shell scripts in a single shell session, try this -- at least, this is how I would do it on *nix... Frankly, I'm not sure this can be done in a windows environment, but it might be worth a try:
    open( SH, "| /path/to/bash" ) or die "Can't open a shell: $!"; my @scripts; { local $/ = undef; for my $file ( "first_shell_script", "second_shell_script" ) { open( SCR, $file ) or die "couldn't read $file: $!"; push @scripts, <SCR>; close SCR; } } print SH $scripts[0]; print SH $scripts[1]; # and then do whatever magical stuff this shell can do, # now that it has these scripts in its arsenal...
Re: Creating bash functions using perls $ENV interface
by sgifford (Prior) on Oct 29, 2003 at 03:15 UTC

    Update:Turns out you can do this. See sauoq's reply above. Sorry for the bad info!

    I don't think functions are inherited across bash shells like you think they are.

    For example, if I type set, I can see a function rs defined in my current shell. If I run /bin/bash --norc from this shell, I no longer see the rs function.

    I think that each time bash starts up, it reads the appropriate rc files and re-defines the functions. If that's the case, you could use the BASH_ENV environment variable (see bash(1)) to point to a script containing all of the function definitions.

    Another thing worth noting, although it may not be useful in your case: The easiest way to pass information like function definitions back to the shell from Perl is to print the definitions to stdout, then run something like eval `perl script.pl` in the shell.

      Another thing worth noting, although it may not be useful in your case

      I'm guess it isn't useful in this case. If I read it correctly, he wants to make functions available to his subprocesses (which is doable) rather than trying to make something available to his parent process (which is not doable without jumping through hoops like this one.)

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: Creating bash functions using perls $ENV interface (not an answer)
by The Mad Hatter (Priest) on Oct 29, 2003 at 03:37 UTC
    This is one time I wish I could ++ some nodes more than once. An excellently composed and very interesting/intriguing question, I'm sure many monks here will pick up a new trick from this thread as I did. Well done (to both tid and sauoq)!
Re: Creating bash functions using perls $ENV interface
by TomDLux (Vicar) on Oct 29, 2003 at 04:28 UTC

    In bash, or other shells, you have your functions in a library file, say myLib, which you load into a script with the command source myLib.

    In Perl, the file is called a module, myModule.pm, and you access it with use myModule; or less oftenrequire myModule; or rarely do myModule.pm;

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: Creating bash functions using perls $ENV interface
by tid (Beadle) on Oct 30, 2003 at 01:19 UTC

    Hey guys, I have another related question....

    I have a WindowsXP system running ActivePerl 5.8.0. I've defined the environment functions as described in the discussion above, but I've noticed that somewhere along the line, the function names are being made into all caps. ie this works

    #!perl -w $CYGWIN_BIN="C:\\cygwin\\bin"; $ENV{TEST_FUNC} = "() {\necho Hey, it works!;\n };\n"; system(("$CYGWIN_BIN\\bash.exe", "-c \"declare -f\"")); system(("$CYGWIN_BIN\\bash.exe", "-c \"TEST_FUNC\""));

    ....whereas this doesn't:

    #!perl -w $CYGWIN_BIN="C:\\cygwin\\bin"; $ENV{test_func} = "() {\necho Hey, it works!;\n };\n"; system(("$CYGWIN_BIN\\bash.exe", "-c \"declare -f\"")); system(("$CYGWIN_BIN\\bash.exe", "-c \"test_func\""));

    Any ideas? This could be an issue with the windows environment, and could explain the reason why sauoqs solution didn't work for me....

    Cheers guys!
    Mike

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://302896]
Approved by sauoq
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-04-25 05:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found