通过Perl脚本设置环境变量[重复]

时间:2022-06-01 17:09:37

This question already has an answer here:

这个问题在这里已有答案:

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

我试图通过Perl脚本以下列方式设置环境变量LD_LIBRARY_PATH:

I have created .profile under /root

我在/ root下创建了.profile

.profile has an export command say:

.profile有一个导出命令说:

export LD_LIBRARY_PATH=/

My Perl script is test.pl and it has:

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

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

When I execute ./test.pl, LD_LIBRARY_PATH doesn't change.

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

What am I doing wrong?

我究竟做错了什么?

5 个解决方案

#1


11  

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_PATH only in that shell process.

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

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 %ENV says:

正如perldoc -v%ENV所说:

%ENV The hash %ENV contains 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_PATH in your current interactive shell process. To do that, you can have you Perl script print a shell command that will update $LD_LIBRARY_PATH. Then, rather than simply running your Perl script, you can execute it and then evaluate its output. For example:

我假设您要在当前的交互式shell进程中更新$ LD_LIBRARY_PATH。为此,您可以让Perl脚本打印一个将更新$ LD_LIBRARY_PATH的shell命令。然后,您可以执行它,然后评估其输出,而不是简单地运行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 unexported variables 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/.profile implies that you're doing things as root (superuser). This can be dangerous. Use the root account (either by logging into it or via sudo only for things that actually need root privileges. For anything else, use a personal user account.

(一个注意事项,与您的问题没有直接关系:您正在使用/root/.profile这一事实意味着您正在以root身份执行操作(超级用户)。这可能很危险。使用root帐户(通过记录进入它或通过sudo仅用于实际需要root权限的东西。对于其他任何东西,使用个人用户帐户。

#2


5  

system starts 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).

系统启动一个新进程,并且改变环境不会影响脚本进程中的环境(通常 - 通常是依赖于os的方法来更改其他进程的环境)。

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} = '/';

#3


3  

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

要更改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 eval to execute the resulting commands:

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

Perl script:

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

Shell script:

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

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

有关这样工作的命令的示例,请参阅tset和ssh-agent。

#4


2  

This can now be done with the Env::Modify module:

现在可以使用Env :: Modify模块完成此操作:

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

#5


1  

You can't do it.

你不能这样做。

This is from the Perl FAQ:

这来自Perl FAQ:

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魔法可能允许你通过eval()在shell中输出脚本的输出来伪造它;有关详细信息,请查看comp.unix.questions常见问题解答。

#1


11  

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_PATH only in that shell process.

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

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 %ENV says:

正如perldoc -v%ENV所说:

%ENV The hash %ENV contains 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_PATH in your current interactive shell process. To do that, you can have you Perl script print a shell command that will update $LD_LIBRARY_PATH. Then, rather than simply running your Perl script, you can execute it and then evaluate its output. For example:

我假设您要在当前的交互式shell进程中更新$ LD_LIBRARY_PATH。为此,您可以让Perl脚本打印一个将更新$ LD_LIBRARY_PATH的shell命令。然后,您可以执行它,然后评估其输出,而不是简单地运行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 unexported variables 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/.profile implies that you're doing things as root (superuser). This can be dangerous. Use the root account (either by logging into it or via sudo only for things that actually need root privileges. For anything else, use a personal user account.

(一个注意事项,与您的问题没有直接关系:您正在使用/root/.profile这一事实意味着您正在以root身份执行操作(超级用户)。这可能很危险。使用root帐户(通过记录进入它或通过sudo仅用于实际需要root权限的东西。对于其他任何东西,使用个人用户帐户。

#2


5  

system starts 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).

系统启动一个新进程,并且改变环境不会影响脚本进程中的环境(通常 - 通常是依赖于os的方法来更改其他进程的环境)。

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} = '/';

#3


3  

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

要更改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 eval to execute the resulting commands:

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

Perl script:

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

Shell script:

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

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

有关这样工作的命令的示例,请参阅tset和ssh-agent。

#4


2  

This can now be done with the Env::Modify module:

现在可以使用Env :: Modify模块完成此操作:

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

#5


1  

You can't do it.

你不能这样做。

This is from the Perl FAQ:

这来自Perl FAQ:

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魔法可能允许你通过eval()在shell中输出脚本的输出来伪造它;有关详细信息,请查看comp.unix.questions常见问题解答。