【问题标题】:Setting an environment variable through a Perl script [duplicate]通过 Perl 脚本设置环境变量 [重复]
【发布时间】:2013-10-12 03:04:46
【问题描述】:

我正在尝试通过 Perl 脚本以下列方式设置环境变量 LD_LIBRARY_PATH

我在/root下创建了.profile

.profile 有一个export 命令说:

export LD_LIBRARY_PATH=/

我的 Perl 脚本是 test.pl,它有:

#!/usr/bin/perl
system(". /root/.profile");

当我执行./test.pl 时,LD_LIBRARY_PATH 不会改变。

我做错了什么?

【问题讨论】:

  • 你不能改变另一个进程的环境。
  • 只能改变进程本身的环境。然后这个环境将被它产生的子进程继承。由于system() 在 perl 的子进程中运行 shell 命令,因此它所做的任何环境更改都不会影响 perl,也不会影响调用 perl 的 shell。
  • 那么如何在 perl 脚本中更改环境变量?

标签: linux perl bash sh


【解决方案1】:

现在可以使用Env::Modify module

use Env::Modify 'source';
source("/root/.profile");
... env settings of .profile are now available to Perl ...

【讨论】:

    【解决方案2】:

    system 启动一个新进程,并且更改那里的环境不会影响脚本进程中的环境(通常——通常有依赖于操作系统的方法来更改其他进程的环境)。

    perl 程序中的环境与%ENV 相关联,这有点像(实际上不是)绑定到环境的散列:改变它会改变环境。因此:

    $ENV{LD_LIBRARY_PATH} = '/';
    

    【讨论】:

      【解决方案3】:

      要更改 Perl 脚本中的环境,请分配给 %ENV 哈希:

      $ENV{'LD_LIBRARY_PATH'} = '/';
      

      如果你想编写一个被 shell 用来改变其环境的程序,通常的做法是让脚本将 shell 命令写入标准输出。然后,shell 使用命令替换执行此操作,并使用 eval 执行生成的命令:

      Perl 脚本:

      #!/usr/bin/perl
      print 'LD_LIBRARY_PATH=\n';
      

      Shell 脚本:

      eval "$(/path/to/perlscript)"
      

      有关这样工作的命令示例,请参阅tsetssh-agent

      【讨论】:

      • #!/usr/bin/perl $ENV{'LD_LIBRARY_PATH'} = '/'; 在 test.pl 并执行 ./test.pl 仍然 LD_LIBRARY_PATH 保持不变
      • 这是因为改变 perl 脚本中的环境不会对启动 perl 脚本的 shell 环境产生任何影响。
      • 您问如何更改 perl 脚本中的环境变量? 我的回答改变了 perl 脚本中的环境,它不会改变父 shell 中的环境。正如我在评论中所说,以及其他人在他们的回答中解释的那样,您无法在另一个进程中更改环境 - 您只能在自己的进程中更改它,并且它将被孩子继承。
      【解决方案4】:

      你做不到。

      这是来自the Perl FAQ

      从最严格的意义上说,它是无法完成的——脚本作为与它启动时所在的 shell 不同的进程执行。对流程的更改不会反映在其父进程中 - 只会反映在更改后创建的任何子进程中。有一种 shell 魔法可以让你通过在你的 shell 中对脚本的输出进行 eval() 来伪造它;详情请查看 comp.unix.questions 常见问题解答。

      【讨论】:

        【解决方案5】:

        您当前的脚本甚至不会更改 Perl 脚本本身的环境变量。相反,它调用一个 shell 作为一个子进程。该 shell 进程执行 . /root/.profile,它仅在该 shell 进程中更新 $LD_LIBRARY_PATH

        您可以通过更新%ENV 来更改 Perl 脚本中的环境变量(更准确地说,是在运行 Perl 脚本的进程中):

        $ENV{LD_LIBRARY_PATH} = '/'; # or some more reasonable value
        

        正如perldoc -v %ENV 所说:

        %ENV 哈希%ENV 包含您当前的环境。在“ENV”中设置一个值会更改您随后“fork()”关闭的任何子进程的环境。

        但这可能仍然无法满足您的要求;它不会(也不能)影响调用 Perl 脚本(您的交互式 shell)的进程的环境,只会影响 Perl 进程本身及其调用的任何东西。

        我假设您想在当前的交互式 shell 进程中更新 $LD_LIBRARY_PATH。为此,您可以让您的 Perl 脚本打印一个 shell 命令,它将更新 $LD_LIBRARY_PATH。然后,您可以执行它,然后评估它的输出,而不是简单地运行您的 Perl 脚本。例如:

        $ cat env.pl
        #!/usr/bin/perl
        
        use strict;
        use warnings;
        
        print "export LD_LIBRARY_PATH=/\n";
        $ ./env.pl          # just prints the command without executing it
        export LD_LIBRARY_PATH=/
        $ eval $(./env.pl)  # executes the command in the current shell
        $ echo $LD_LIBRARY_PATH 
        /
        $ 
        

        这假设您当前的 shell 是 bash 或类似的。

        另一个选项:修改%ENV 后,您的 Perl 脚本可以调用另一个命令,甚至是一个新的交互式 shell。新进程将从 Perl 脚本继承其环境。不过,这可能有点麻烦。例如,如果新进程是交互式 shell,它不会从父 shell 继承未导出变量或历史记录。

        (一个注释,与您的问题没有直接关系:您与/root/.profile 搞混的事实意味着您正在以root(超级用户)的身份做事。这可能很危险。使用root帐户(通过登录或通过 sudo 仅用于实际需要 root 权限的内容。对于其他任何事情,请使用个人用户帐户。

        【讨论】:

        • 嘿,我可以从另一个 perl 脚本调用 eval($./env.pl),如果可以的话,使用系统命令说 test.pl 你能解释一下吗?
        • @user2848437:不是那种语法。 Perl 确实具有捕获外部命令输出的语法,使用反引号或qx/string/perldoc perlop 并搜索“Quote-Like Operators”)。它有一个eval 函数(perldoc -f eval)——当然Perl 的eval 需要一个带有Perl 语法的参数,而不是shell 语法。但是有更好的方法可以从 Perl 脚本调用 Perl 代码:将代码放在模块中并调用它,或者只是将代码复制到您的脚本中。
        猜你喜欢
        • 1970-01-01
        • 2019-05-17
        • 2016-12-23
        • 1970-01-01
        • 2023-03-03
        • 2019-07-21
        • 1970-01-01
        • 1970-01-01
        • 2019-05-30
        相关资源
        最近更新 更多