2

您可以阅读环境变量

$envVarVal = $ENV{'VAR_NAME'};

反向设置它不起作用,即一旦脚本完成运行,您将看不到 var:

$ENV{'VAR_NAME'} = 'some_val';

我还尝试了一个系统调用:

`export VAR_NAME=some_val`;

在 Perl 脚本中调用成功,但变量再次超出范围不可见。

是否有可能做到这一点,如果没有,为什么不能在 Perl 中做到这一点,而是通过采购一个常规的 shell 脚本,任何 shell,据我所知?

4

3 回答 3

13

是的,使用 VMS。

这可能不是最实用的建议,但它是完整的。:)

VMS 是……不同的。VMS 和 Unix 可能比 Windows 和 Unix 更不同。Perl 是围绕 Unix 思维构建的,并且必须将这些 Unix 概念中的一些延伸到断点,以便将它们包装在 VMS 的做事方式上。其中之一是什么%ENV意思。

VMS 没有 Unix 那样的环境变量。VMS 最接近的东西是逻辑名称。它们是一个键/值对表,其用途类似于环境变量和 shell 别名。与 Unix 上的环境变量和 Ogres 不同,它们有层。

来自OpenVMS 顾问:逻辑名称(第 1 部分)

大多数进程与至少四个逻辑名称表(进程、作业、组和系统)相关联。通常通过首先按层次顺序搜索 Process、Job、Group 和 System 表来翻译名称。高级用户可以控制搜索和翻译过程。此外,出于安全和完整性原因,某些翻译排除了最终用户定义的逻辑名称。

在 Unix 上,环境表被复制到一个进程中,因此该进程不会对其父进程产生任何影响。在 VMS 上,逻辑表是一个堆栈。VMS 读取该堆栈,直到找到一个值。例如,如果您要求SYS$OUTPUT(例如STDOUT)的值,它将首先检查进程的逻辑表,然后是作业,然后是组,最后是整个系统的值。通过这种方式,操作系统可以SYS$OUTPUT在系统表中定义一个默认值,但它可以被您或单个进程覆盖。

如果这看起来很复杂,它实际上是对真正发生的事情的简化。

逻辑是一个堆栈,那么如果你设置一个会发生什么?

最后,对于这个答案,$ENV{FOO} = "BAR"将查找逻辑表堆栈并分配给它找到的第一个 FOO。如果进程表中有一个,它将分配给它。如果工作表中有一个,它将分配给它。以此类推,直到达到其写入权限的限制。此时它将在其最高的表中创建一个新条目,可能是作业表。这意味着$ENV{FOO} = "BAR"很可能会出现在工作表中,因此您的所有流程都可以看到。

这就是在 Perl 中在一个进程中设置环境变量并导出到另一个进程的方式。

于 2012-11-30T22:50:01.063 回答
8

这在大多数系统上是不可能的,不仅在 perl 中,在 shell 中也是如此。每个进程都有自己的从父进程继承的环境副本,并且对环境的任何更改只会影响该进程及其创建的任何子进程(在对环境进行更改之后)。

在 perl 中设置的环境变量$ENV{VAR_NAME} = 'some_val';将可用于之后由 perl 脚本创建的进程。就像由 shell 脚本设置的环境变量export VAR_NAME=some_val将反映在该脚本以后创建的任何进程中一样。

shell函数或获取 shell 脚本(使用source scriptname. scriptname)可以更改比函数或源脚本更有效的环境。但这只是可能的,因为没有创建新进程来运行该代码,它将在调用它的同一进程中运行。

使用 perl 的反引号操作符来运行export是没有意义的。这将成功,因为这会导致 perl 启动一个设置了环境变量的新 shell 进程,但随后该进程将立即退出而不做任何有用的事情。

echo $$通过使用显示进程 ID,您可以在一定程度上看到这一点。在运行之前尝试在您提供的 shell 脚本中运行相同的脚本而不使用它,并在使用 perl 的反引号运算符执行的 shell 代码中运行脚本。进程 ID 也可以从 perl 中使用print $$, "\n";.

于 2012-11-30T22:05:33.833 回答
6

这不可能。但是,您可以告诉 Perl 为您创建一个脚本,然后对其进行 source 或 eval:

#!/bin/bash
eval $(perl -e 'print "VAR1=", rand 1')
perl -e 'print "VAR2=", rand 1' > var2.sh
. var2.sh
rm var2.sh
echo $VAR1 $VAR2
于 2012-11-30T22:30:29.567 回答