如何在Perl脚本中重新加载Bash环境变量?
有没有一种方法可以从Perl脚本中加载Bash环境变量(通过从Bash shell中获取如何在Perl脚本中重新加载Bash环境变量?,bash,perl,Bash,Perl,有没有一种方法可以从Perl脚本中加载Bash环境变量(通过从Bash shell中获取~/.bashrc来定义)。具体来说,我感兴趣的是在Perl脚本的调用方不是bashprocess1的子对象的情况下重新加载PERL5LIB环境变量。在这种情况下,$ENV{PERL5LIB}将不存在,这将阻止我使用我在主目录中安装的任何模块 第一次尝试可以是使用-l选项在bash下重新运行我自己。这将加载~/.bash\u profile,我已将该文件设置为加载~/.bashrc #! /usr/bin/e
~/.bashrc
来定义)。具体来说,我感兴趣的是在Perl脚本的调用方不是bash
process1的子对象的情况下重新加载PERL5LIB
环境变量。在这种情况下,$ENV{PERL5LIB}
将不存在,这将阻止我使用我在主目录中安装的任何模块
第一次尝试可以是使用-l
选项在bash
下重新运行我自己。这将加载~/.bash\u profile
,我已将该文件设置为加载~/.bashrc
#! /usr/bin/env perl
use strict;
use warnings;
if ( !exists $ENV{PERL5LIB} ) {
exec 'bash', '-lc', $0, @ARGV;
}
else {
# Main program starts here..
}
但是,对于~/.bashrc
中未定义PERL5LIB
的(意外)情况,这可能会进入无限循环
脚注:
[1] 我在尝试使用google chrome扩展API从google chrome
进程编写要调用的本机主机时遇到了这种特殊情况。
可以通过shell脚本修改您的环境
差不多
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
}
(显然,使用Getopt::Long或类似的方法会更好。)
这不仅符合您的规范,而且在需要时提供了一个旁路
也就是说,整个概念是有缺陷的。大多数人不应该使用PERL5LIB,修复配置不好的系统(那些需要PERL5LIB但在应该设置时没有设置PERL5LIB的系统)也不是你的工作。相反,.听起来您的扩展应该在扩展本身的同时安装任何非标准库,然后您可以硬编码(相对)路径,并在启动时将其添加到
@INC
,而不需要用户管理它(以及您的库与他们实际需要的库之间可能存在的冲突)。如果您只想从主目录加载模块,那么为什么不在主目录上使用lib
,而不依赖环境变量?您的脚本甚至不知道调用方是否使用bash
;调用时,调用方有责任确保PERL5LIB
具有适当的值g脚本。@chepner在我的用例中,调用者是google chrome
,我同意奇怪的是,它没有为其子进程设置PERL5LIB
。也就是说,PERL5LIB
可能应该从.bash\u profile
中定义一次并继承,而不是每次设置interactive shell已启动。不过,我不知道google chrome
是否是从您的登录shell中派生的进程启动的。谢谢,但现在的问题是Env::Modify
也安装在我的主目录中(我使用的是cpanm
)。谢谢你的代码。但是我很难理解它。传递给bash
的参数:为什么$0
传递了两次?以及$@
在做什么?脚本后的第一个参数被放入$0
,下一个在$1
中,下一个在$2
中,等等。“$@”
相当于“$1”“$2”“$3”“。
。请注意,我们不使用$0
,因此可以为其传递任何值。请将bash-c echo foo bar
与bash-c'$@”进行比较“dummy echo foo bar
谢谢,现在对我来说很有意义。但是为什么我们不应该使用PERL5LIB
?我一直在使用它。首先,我安装cpan App::cpanminus
;在这个初始安装时,cpan
会询问我是在我的主目录还是在系统目录中安装(需要root权限)。我总是选择在我的主目录中安装。然后,我需要设置PERL5LIB。事实上,如果您配置了cpanm
,那么您也配置了cpan
。@HåkonHægland您的发行版已经安装了许多模块,因此不可能只使用cpan。您不会经常看到问题,但它们确实存在没有理由冒这种不必要的风险,因为安装额外的perl副本非常容易。您应该发布关于perlbrew问题的另一个问题。
#! /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);
}
}
...