views:

417

answers:

9

I have a script whose content simply exports a variable in linux.

export LD_LIBRARY_PATH=....

I want to run this script in my Perl script so whoever is running my Perl script will have their LD_LIBRARY_PATH set. Can i just do this in the beginning of my Perl script:

#!/usr/bin/perl -w

system(". /myfolder1/myfolder2/myScript.sh");
+3  A: 

This won't work. There is no way for a subshell to manipulate the environment of the parent process.

But you could make your script echo the string you want to set as LD_LIBRARY_PATH and then from within your Perl script you could do something like that:

$ENV{LD_LIBRARY_PATH} = `path/to/your/script.sh`;

Of course, a bit of error checking might also be a good idea.

innaM
What should i do then?
Saobi
Reverse the process. Call a shell script that sets the variable, and then use it to run the perl script.
Satanicpuppy
See my edited answer. However, since you are trying to set LD_LIBRARY_PATH, it may already be to late to set it when the Perl script is already running. What exactly are you trying to do?
innaM
My perl script calls oracle database, which requires this to be set. And it may be run from other user logins
Saobi
A: 

That won't work. An (unpleasant) alternative might be to replace /usr/bin/perl with a shell script that first executes your script and then executes the perl executable.

Eric
+4  A: 

This won't work. To change the environment inside your Perl script (and to change the environment that will be passed on to commands run from inside your Perl script), change the %ENV variable.

$ENV{"LD_LIBRARY_PATH"} = ... ;
mobrule
ok. this will not run into subshell issues?
Saobi
No, this answer directly manipulates Perl's idea of the environment. Of course, this syntax is not the same as the shell syntax your `myScript.sh` is currently in, and if you still want it in an external file, you'll have to `do` or `require` it.
ephemient
But in my original script it does:export LD_LIBRARY_PATH=~myFolder/myFolder2:$LD_LIBRARY_PATHHow do i do that in the $ENV line in oracle?
Saobi
Do you really mean `~myFolder`?? In that case, `$ENV{LD_LIBRARY_PATH} = (getpwnam("myFolder"))[7] . "/myFolder2:$ENV{LD_LIBRARY_PATH}"`.
ephemient
+9  A: 
#!/bin/sh
. /myfolder1/myfolder2/myScript.sh
exec perl -wxS "$0" "$@"
#!/usr/bin/perl -w
# .. the rest of your script as normal

When you run this, it will first be executed by /bin/sh, which is capable of loading myScript.sh into the local environment. sh then execs Perl, which is told to continue from the following line.

ephemient
What does -wxS "$0" "$@" do ?
Saobi
`-w`: warnings on globally, since you had that in your original script. `-x`: Look for `#!perl` line and start executing from there. `-S "$0" "$@"`: look in `$PATH` for `$0` (current script) and pass along all other arguments.
ephemient
The trivial way of accomplishing this is to instead make myScript.sh call the perl script, remembering to pass along arguments.
dlamblin
@dlamblin: That would be easier, but where's the fun in that? ;-) This saves having to rename the Perl script and add a new shell script, not that it should ever matter...
ephemient
A: 

This can't be done in the way you're trying to do this.

It either needs a wrapper shell script that sets LD_LIBRARY_PATH and then calls your perl script, or any user executing the script needs to have LD_LIBRARY_PATH set correctly in the first place.

If doing the latter, then this can be managed globally by editing /etc/profile and /etc/cshrc (for ksh, sh, bash, csh and tcsh) shells. You can then test for the value of LD_LIBRARY_PATH in your script and if not set/set incorrectly then print a friendly message to the user. Alternatively individual users can set this in their local .profile/.cshrc files.

Note: you haven't given any information about the environment or useres that might run this, so there's also the possibility that users may set LD_LIBRARY_PATH to something they need. If you do check LD_LIBRARY_PATH for a "good" value in your script, then keep in mind that several paths may have been specified, so you will need to parse this environment variable properly.

Chris J
+1  A: 

Another option (other than making the changes directly in Perl's %ENV) is to make the changes you want a Perl module, so that you can say:

use MyEnvironment;

and have it modify your environment in all your scripts. It would make it simple to make changes after the fact that will not require editing every script.

The module itself will be simple, something like this:

package MyEnvironment;

$ENV{LD_LIBRARY_PATH} .= ":/some/path/you/want/appended";
# Any other changes you want here.

1;
zigdon
+2  A: 

No. Your environment changes made in a child cannot affect the parent. This means running a script will not affect perl. Also perl will not affect the shell from which it was called. You can edit the environment inside perl by changing the special variable %ENV. If there's some kind of unreproducible calculation done in that script, maybe the script should just echo the setting and perl can pick that up on STDOUT and use it.

I {changed directory, modified my environment} in a perl script. How come the change disappeared when I exited the script? How do I get my changes to be visible?

Unix In the strictest sense, it can't be done -- the script executes as a different process from the shell it was started from. Changes to a process are not reflected in its parent, only in its own children created after the change.

dlamblin
The question is a bit different than the one you are answering.
brian d foy
If so, the question isn't clear; chaining sh then perl as the accepted answer does wasn't even vaguely implied as desirable since the more trivial way of doing it was obvious yet dismissed.
dlamblin
+1  A: 

I had a similar problem a few years ago and whipped up a little module, Env::Sourced, that should do the trick.

 use Env::Sourced qw(/myfolder1/myfolder2/myScript.sh);

...

Josh McAdams
A: 

If you can find the right place in your perl script, this works as in my example:

$ENV{"LD_LIBRARY_PATH"} = "/oracle/product/10g/lib";

And it didn't require me to call another script to set the env var.