Linux 定义带或不带导出的变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1158091/
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-03 17:32:39  来源:igfitidea点击:

Defining a variable with or without export

linuxbashshell

提问by flybywire

What is exportfor?

export为了什么?

What is the difference between:

有什么区别:

export name=value

and

name=value

采纳答案by Brian Agnew

exportmakes the variable available to sub-processes.

export使变量可用于子流程。

That is,

那是,

export name=value

means that the variable name is available to any processyou run from that shell process. If you want a process to make use of this variable, use export, and run the process from that shell.

意味着该变量名称可用于您从该 shell 进程运行的任何进程。如果您希望进程使用此变量,请使用export并从该 shell 运行该进程。

name=value

means the variable scope is restricted to the shell, and is not available to any other process. You would use this for (say) loop variables, temporary variables etc.

意味着变量范围仅限于外壳程序,不能用于任何其他进程。您可以将它用于(例如)循环变量、临时变量等。

It's important to note that exporting a variable doesn't make it available to parent processes. That is, specifying and exporting a variable in a spawned process doesn't make it available in the process that launched it.

请务必注意,导出变量不会使其对父进程可用。也就是说,在衍生进程中指定和导出变量不会使其在启动它的进程中可用。

回答by John T

exportwill make the variable available to all shells forked from the current shell.

export将使该变量可用于从当前 shell 分叉的所有 shell。

回答by alxp

To illustrate what the other answers are saying:

为了说明其他答案的意思:

$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 

回答by William Pursell

Others have answered that export makes the variable available to subshells, and that is correct but merely a side effect. When you export a variable, it puts that variable in the environment of the current shell (ie the shell calls putenv(3)or setenv(3)).
The environment of a process is inherited across exec, making the variable visible in subshells.

其他人已经回答说 export 使变量可用于子shell,这是正确的,但只是副作用。当您导出一个变量时,它会将该变量放在当前 shell 的环境中(即 shell 调用putenv(3)setenv(3))。
进程的环境跨 exec 继承,使变量在子 shell 中可见。

Edit (with 5 year's perspective): this is a silly answer. The purpose of 'export' is to make variables "be in the environment of subsequently executed commands", whether those commands be subshells or subprocesses. A naive implementation would be to simply put the variable in the environment of the shell, but this would make it impossible to implement export -p.

编辑(从 5 年的角度来看):这是一个愚蠢的答案。'export' 的目的是使变量“处于随后执行的命令的环境中”,无论这些命令是子 shell 还是子进程。一个简单的实现是简单地将变量放在 shell 的环境中,但这会使export -p.

回答by William Pursell

Here's yet another example:

这是另一个例子:

VARTEST="value of VARTEST" 
#export VARTEST="value of VARTEST" 
sudo env | grep -i vartest 
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'  

Only by using export VARTEST the value of VARTEST is available in sudo bash -c '...'!

只有使用 export VARTEST 才能在 sudo bash -c '...' 中使用 VARTEST 的值!

For further examples see:

有关更多示例,请参见:

回答by Charles Merriam

export NAME=valuefor settings and variables that have meaning to a subprocess.

export NAME=value用于对子流程有意义的设置和变量。

NAME=valuefor temporary or loop variables private to the current shell process.

NAME=value用于当前 shell 进程私有的临时或循环变量。

In more detail, exportmarks the variable name in the environment that copies to a subprocesses and their subprocesses upon creation. No name or value is ever copied back from the subprocess.

更详细地,export在创建时复制到子流程及其子流程的环境中标记变量名称。不会从子流程中复制任何名称或值。

  • A common error is to place a space around the equal sign:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
    
  • Only the exported variable (B) is seen by the subprocess:

    $ A="Alice"; export B="Bob"; echo "echo A is $A. B is $B" | bash
    A is . B is Bob
    
  • Changes in the subprocess do not change the main shell:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
    
  • Variables marked for export have values copied when the subprocess is created:

    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
    
  • Only exported variables become part of the environment (man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob
    
  • 一个常见的错误是在等号周围放置一个空格:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
    
  • B子进程只能看到导出的变量 ( ):

    $ A="Alice"; export B="Bob"; echo "echo A is $A. B is $B" | bash
    A is . B is Bob
    
  • 子进程中的更改不会更改主 shell:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
    
  • 标记为导出的变量在创建子流程时复制了值:

    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
    
  • 只有导出的变量成为环境的一部分 ( man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob
    

So, now it should be as clear as is the summer's sun! Thanks to Brain Agnew, alexp, and William Prusell.

所以,现在应该和夏天的太阳一样清晰!感谢 Brain Agnew、alexp 和 William Prusell。

回答by Scott

Although not explicitly mentioned in the discussion, it is NOT necessary to use export when spawning a subshell from inside bash since all the variables are copied into the child process.

尽管在讨论中没有明确提到,但在从 bash 内部生成子 shell 时没有必要使用 export,因为所有变量都被复制到子进程中。

回答by Will

Just to show the difference between an exported variable being in the environment (env) and a non-exported variable not being in the environment:

只是为了显示在环境 (env) 中的导出变量和不在环境中的非导出变量之间的区别:

If I do this:

如果我这样做:

$ MYNAME=Fred
$ export OURNAME=Jim

then only $OURNAME appears in the env. The variable $MYNAME is not in the env.

那么只有 $OURNAME 出现在环境中。变量 $MYNAME 不在环境中。

$ env | grep NAME
OURNAME=Jim

but the variable $MYNAME does exist in the shell

但是变量 $MYNAME 确实存在于 shell 中

$ echo $MYNAME
Fred

回答by Matyas Koszik

It has been said that it's not necessary to export in bash when spawning subshells, while others said the exact opposite. It is important to note the difference between subshells (those that are created by (), ``, $()or loops) and subprocesses (processes that are invoked by name, for example a literal bashappearing in your script).

有人说在生成子外壳时没有必要在 bash 中导出,而其他人则说恰恰相反。需要注意的子shell之间的区别是很重要的(那些被创建()``$()或回路)和子(即通过名称调用,如流程文字bash出现在你的脚本)。

  • Subshellswillhave access to all variables from the parent, regardless of their exported state.
  • Subprocesseswill onlysee the exported variables.
  • shell可以访问来自父级的所有变量,无论它们的导出状态如何。
  • 进程看到导出的变量。

What is common in these two constructs is that neither can pass variables back to the parent shell.

这两种结构的共同点是都不能将变量传递回父 shell。

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:

There is one more source of confusion: some think that 'forked' subprocesses are the ones that don't see non-exported variables. Usually fork()s are immediately followed by exec()s, and that's why it would seem that the fork() is the thing to look for, while in fact it's the exec(). You can run commands without fork()ing first with the execcommand, and processes started by this method will also have no access to unexported variables:

还有一个混乱的来源:有些人认为“分叉”子流程是那些看不到非导出变量的子流程。通常 fork()s 后面紧跟 exec()s,这就是为什么看起来 fork() 是要查找的东西,而实际上它是 exec()。您可以在不使用 fork() 的情况下先使用exec命令运行命令,并且由此方法启动的进程也将无法访问未导出的变量:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

Note that we don't see the parent:line this time, because we have replaced the parent shell with the execcommand, so there's nothing left to execute that command.

请注意,这次我们没有看到该parent:行,因为我们已经用exec命令替换了父 shell ,因此没有任何东西可以执行该命令。

回答by Amjad

By default, variables created within a script are only available to the current shell; child processes (sub-shells) will not have access to values that have been set or modified. Allowing child processes to see the values, requires use of the export command.

默认情况下,在脚本中创建的变量仅对当前 shell 可用;子进程(子外壳)将无法访问已设置或修改的值。允许子进程查看值需要使用 export 命令。