2

Is there a way to load Bash environment variables ( defined by sourcing ~/.bashrc from a Bash shell ) from within a Perl script. Specifically, I am interested in reloading the PERL5LIB environment variable in the case the caller of the Perl script is not a child of a bash process1. In that case, $ENV{PERL5LIB} will not exist, which will prevent me from using any modules I have installed in my home directory.

A first attempt could be to rerun my myself under bash with the -l option. This will load ~/.bash_profile, and I have set that file up to load ~/.bashrc.

#! /usr/bin/env perl

use strict;
use warnings;

if ( !exists $ENV{PERL5LIB} ) {    
    exec 'bash', '-lc', $0, @ARGV;
}
else {
    # Main program starts here..
}

But this could enter an infinite loop for the (unexpected) case that PERL5LIB is not defined in ~/.bashrc.

Footnotes:

[1] This specific case occured for me when trying to write a native host to be called from the google-chrome process using the Google Chrome Extension API.

10
  • Sounds like your extension should install any nonstandard libraries along with the extension itself, and then you can hard-code the (relative) path and add it to @INC when you start up, rather than require the user to manage this (and any possible conflict between your libraries and those they actually want for their own needs). Commented Oct 4, 2016 at 13:18
  • If all you want to do is to load modules from your home directory, then why not do a use lib on your home directory instead of relying on the environment variable? Commented Oct 4, 2016 at 13:18
  • 5
    Your script doesn't even know if the caller uses bash; it's the caller's responsibility to make sure PERL5LIB has an appropriate value when calling the script. Commented Oct 4, 2016 at 13:28
  • 1
    @chepner For my use case the caller is google-chrome, and I agree that it is strange that it does not setup PERL5LIB for its child processes. Commented Oct 4, 2016 at 13:47
  • That said, PERL5LIB is probably something that should be defined once from .bash_profile and inherited, rather than setting every time an interactive shell is started. I don't know if google-chrome is being launched from a process that descends from an appropriate login shell in your case, though. Commented Oct 4, 2016 at 15:37

2 Answers 2

6

Env::Modify can modify your environment from shell scripts.

Something like

use Env::Modify 'source';

# BEGIN { ???
if (!exists($ENV{PERL5LIB})) {
    source("$ENV{HOME}/.bashrc");
    die "PERL5LIB not in .bashrc" unless $ENV{PERL5LIB};
    exec($^X, $0, @ARGV);     # restart
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, but the problem now is that Env::Modify is also installed in my home directory ( I am using cpanm ).
0
#! /usr/bin/env perl

use strict;
use warnings;

BEGIN {
    if (!exists( $ENV{PERL5LIB} )) {    
        if (!@ARGV || $ARGV[0] ne '--no-restart') {
            exec('bash', '-lc', '"$@"', $0, $^X, $0, '--no-restart', @ARGV);
        }
    }

    if (@ARGV && $ARGV[0] eq '--no-restart') {
        shift(@ARGV);
    }
}

...

(Obviously, using Getopt::Long or some-such would be better.)

This not only meets your spec, but provides a bypass if needed.

That said, the whole concept is flawed. Most people shouldn't be using PERL5LIB, and it's not your job to fix badly configured systems (those that need PERL5LIB but don't have it set when it should be set). Instead, fix your environment.

21 Comments

Thanks for the code. But I have some difficulty of getting my head around it. The arguments that is passed to bash: Why is $0 passed twice? And what is $@ doing?
The first argument after the script is put in $0, the next in $1, the next in $2, etc. "$@" is equivalent to "$1" "$2" "$3" .... Notice we don't use $0, so we could pass any value for it. Compare bash -c echo foo bar with bash -c '"$@"' dummy echo foo bar
Thanks, it makes sense to me now. But why shouldn't we use PERL5LIB? I have always been using it. First I install cpan App::cpanminus; at this initial install cpan will ask if I will install in my home directory or in the system directory ( requires root privileges ). I always choose to install in my home directory. Then, I need to set PERL5LIB.
In fact, if you've configured cpanm to do so, you've also configured cpan to do so.
@HåkonHægland Your distro already comes with a number of modules installed, so it's not possible to only use cpan. You won't see issues often, but they do happen; there's no reason to risk such needless problems because it's incredibly easy to install additional copies of perl. You should post another question about your perlbrew issues.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.