Weird environment variables that aren't in Perl's ENV hash

不羁岁月 提交于 2020-03-01 17:32:35

问题


Perl has access to some environment variables:

> echo $HOST
xtt006
> perl -E 'say $ENV{HOST}'
xtt006
> perl -E 'say `echo \$HOST`'
xtt006

But apparently there's another class of environment variables that aren't in the ENV hash:

> echo $env
opsd
> perl -E 'say $ENV{env}'
(no response from Perl)
> perl -E 'say `echo \$env`'
(no response from Perl)

What's up with that? Is there another technique by which Perl can obtain the value of $env?


回答1:


Try exporting your variable from the shell. This will move it from the shell's variable list to the environment that all subprocesses will be able to see.

export env
perl -E 'say $ENV{env}'

This should get it to show up.




回答2:


From %ENV in perlvar   (my emphasis)

The hash %ENV contains your current environment.

The environment is inherited from the process that started the Perl process, here the shell.

However, shell variables can be local, which aren't passed to child processes, or global, that form the environment and are inherited by child processes. The global ones are mostly read from configuration files at startup, but if they are to be added later then they need be exported

A variable created like the ones in the example above is only available to the current shell. It is a local variable: child processes of the current shell will not be aware of this variable. In order to pass variables to a subshell, we need to export them using the export built-in command. Variables that are exported are referred to as environment variables. Setting and exporting is usually done in one step:

export VARNAME="value" 

(my emphasis)   By your description it seems that $env is added as a local variable (with set), which then also need be exported (export env) in order to be seen in the one-liner.

Environment variables can be listed with env or printenv, while set lists all variables, both local and environment ones.


The above refers to the bash shell. The notion of "environment" is the same in other shells, and the same reasoning applies there as well; for a variable to be seen in child processes we need to make it global ("environment variable"). The difference is in how to do this.

In csh/tcsh use

setenv env "value"

instead of set var = "value", what would create a local variable.


Apart from using a global ("environment") variable instead of a local one, one can pass the variable to Perl code. See this post and this post for examples of doing that with one-liners. If an actual script is invoked then make it take arguments; the standard, and nicest, way is with Getopt::Long,

This isn't a special requirement on the users; they use your script and need to invoke it suitably.




回答3:


Just like Perl has private variables (my $x) and environment variables ($ENV{Y}), so does the shell.

$ perl <<'.'
my $x = "x";
$ENV{Y}="Y";
system 'echo "<$x> <$Y>"';
.
<> <Y>

$ sh <<'.'
x=x
export Y=Y
perl -le'print "<$x> <$ENV{Y}>";'
.
<> <Y>

$ csh <<'.'
set x x
setenv Y Y
perl -le'print "<$x> <$ENV{Y}>";'
.
<> <Y>

Having support for private variables is a good thing, not a strange thing.

In your example, $HOST is an environment variable (uppercase by convention), while $env is a private variable (lowercase by convention).


sh and bash

These shells use the same mechanism to assign to private variables and environment variables.

To create an environment variable, one promotes a private variable to an environment using export.

VAR=val
export VAR
perl -e'...$ENV{VAR}...'

or

export VAR
VAR=val
perl -e'...$ENV{VAR}...'

The promotion and assignment can be combined.

export VAR=val
perl -e'...$ENV{VAR}...'

The above approaches change the environment for the shell, and all subsequent children it creates. The following approach can be used to change a specific child's environment:

VAR=val perl -e'...$ENV{VAR}...'

That approach can also be used to effectively promote a private variable:

var=val
VAR="$var" perl -e'...$ENV{VAR}...'

csh and tcsh

These shells use different syntax for setting private variables and environment variables.

To set a private variable, one uses set.

set var val

To set an environment variable, one uses setenv.

setenv VAR val
perl -e'...$ENV{VAR}...'

The above approaches change the environment for the shell, and all subsequent children it creates.



来源:https://stackoverflow.com/questions/55752593/weird-environment-variables-that-arent-in-perls-env-hash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!