Linux 通过 Perl 脚本设置环境变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19192682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:00:41  来源:igfitidea点击:

Setting an environment variable through a Perl script

linuxperlbashsh

提问by user2848437

I am trying to set an environment variable, LD_LIBRARY_PATH, through a Perl script in the following way:

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

I have created .profileunder /root

我创建了.profile/root

.profilehas an exportcommand say:

.profile有一个export命令说:

export LD_LIBRARY_PATH=/

My Perl script is test.pland it has:

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

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

When I execute ./test.pl, LD_LIBRARY_PATHdoesn't change.

当我执行时./test.plLD_LIBRARY_PATH不会改变。

What am I doing wrong?

我究竟做错了什么?

回答by Barmar

To change the environment in a Perl script, assign to the %ENVhash:

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

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

If you want to write a program that's used by a shell to change its environment, the way this is generally done is to have the script write shell commands to stdout. The shell then executes this with command substitution and uses evalto execute the resulting commands:

如果您想编写一个 shell 用来改变其环境的程序,通常这样做的方法是让脚本将 shell 命令写入 stdout。然后 shell 使用命令替换eval来执行它,并使用它来执行生成的命令:

Perl script:

Perl 脚本:

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

Shell script:

外壳脚本:

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

For examples of commands that work like this, see tsetand ssh-agent.

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

回答by muhmuhten

systemstarts a new process, and changing the environment there won't affect the environment in the process of your script (usually—there are generally os-dependent means of changing other processes' environments).

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

The environment in a perl program is associated with %ENV, which is kind of like (it isn't actually) a tied hash to the environment: changing it will change the environment. Thus:

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

$ENV{LD_LIBRARY_PATH} = '/';

回答by Keith Thompson

Your current script doesn't even change an environment variable in the Perl script itself. Rather, it invokes a shell as a subprocess; that shell process executes . /root/.profile, which updates $LD_LIBRARY_PATHonly in that shell process.

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

You can change an environment variable in a Perl script (more precisely, in the process running the Perl script) by updating %ENV:

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

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

As perldoc -v %ENVsays:

正如perldoc -v %ENV所说:

%ENVThe hash %ENVcontains your current environment. Setting a value in "ENV" changes the environment for any child processes you subsequently "fork()" off.

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

But that probably still won't do what you want; it won't (and can't) affect the environment of the process that invokes the Perl script (your interactive shell), only the Perl process itself and anything it invokes.

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

I'll assume you want to update $LD_LIBRARY_PATHin your current interactive shell process. To do that, you can have you Perl script print a shell commandthat will update $LD_LIBRARY_PATH. Then, rather than simply running your Perl script, you can execute it and then evaluate its output. For example:

我假设您想$LD_LIBRARY_PATH在当前的交互式 shell 进程中进行更新。为此,您可以让 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 
/
$ 

This assumes that your current shell is bash or something similar.

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

Another option: After modifying %ENV, your Perl script can invoke another command, even a new interactive shell. The new process will inherit its environment from the Perl script. This can be a bit cumbersome, though; for example, if the new process is an interactive shell, it won't inherit unexportedvariables or history from the parent shell.

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

(One note, not directly related to your question: The fact that you're messing with /root/.profileimplies that you're doing things as root(superuser). This can be dangerous. Use the rootaccount (either by logging into it or via sudoonly for things that actually need root privileges. For anything else, use a personal user account.

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

回答by Andy Lester

You can't do it.

你不能这样做。

This is from the Perl FAQ:

这是来自Perl 常见问题解答

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 any children created after the change. There is shell magic that may allow you to fake it by eval()ing the script's output in your shell; check out the comp.unix.questions FAQ for details.

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

回答by mob

This can now be done with the Env::Modifymodule:

这现在可以通过Env::Modify模块来完成:

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