bash 在程序执行的同一行上设置环境变量与单独设置不同吗?- shell 变量与环境变量

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

Setting an environment variable on same line as program execution is different than setting it separately? - shell variables vs. environment variables

bashshellenvironment-variablescommand-line-arguments

提问by user1902689

What is the difference between:

有什么区别:

prompt$   TSAN_OPTIONS="suppressions=/somewhere/file" ./myprogram

and

prompt$   TSAN_OPTIONS="suppressions=/somewhere/file"
prompt$   ./myprogram

The thread-sanitizerlibrary gives the first case as how to get their library (used within myprogram) to read the file given in options. I read it, and assumed it was supposed to be two separate lines, so ran it as the second case.

线程消毒图书馆给人的第一情况下,如何让自己的图书馆(myprogram内使用)来读取选项中指定的文件。我读了它,并假设它应该是两个单独的行,因此将其作为第二种情况运行。

The library doesn't use the file in the second case, where the environment variable and the program execution are on separate lines.

在第二种情况下,库不使用该文件,其中环境变量和程序执行在不同的行上。

What's the difference?

有什么不同?

Bonus question: How does the first case even run without error? Shouldn't there have to be a ; or && between them? The answer to this question likely answers my first...

额外的问题:第一个案例如何在没有错误的情况下运行?不应该有一个; 或&&它们之间?这个问题的答案可能会回答我的第一个...

回答by Etan Reisner

The format VAR=value commandsets the variable VARto have the value valuein the environment of the command command. The spec section covering this is the Simple Commands. Specifically:

该格式VAR=value command将变量设置VAR为具有value命令环境中的值command。涵盖此内容的规范部分是Simple Commands。具体来说:

Otherwise, the variable assignments shall be exported for the execution environment of the command and shall not affect the current execution environment except as a side-effect of the expansions performed in step 4.

否则,应为命令的执行环境导出变量赋值,并且不应影响当前执行环境,除非作为步骤 4 中执行的扩展的副作用。

The format VAR=value; commandsets the shell variable VARin the current shelland then runs commandas a child process. The child process doesn't know anything about the variables set in the shell process.

该格式在当前 shell 中VAR=value; command设置 shell 变量,然后作为子进程运行。子进程对 shell 进程中设置的变量一无所知。VARcommand

The mechanism by which a process exports (hint hint) a variable to be seen by child processes is by setting them in its environment before running the child process. The shell built-in which does this is export. This is why you often see export VAR=valueand VAR=value; export VAR.

进程导出(提示提示)子进程可见的变量的机制是在运行子进程之前在其环境中设置它们。执行此操作的内置 shell 是export. 这就是为什么你经常看到export VAR=valueVAR=value; export VAR

The syntax you are discussing is a short-form for something akin to:

您正在讨论的语法是类似于以下内容的简短形式:

VAR=value
export VAR
command
unset -v VAR

only without using the current process environment at all.

只是根本不使用当前的进程环境。

回答by mklement0

To complement Etan Reisner's helpful answer:

为了补充Etan Reisner 的有用答案

It's important to distinguish between shellvariables and environmentvariables:

这是区分重要的外壳变量和环境变量

Note: The following applies to allPOSIX-compatible shells; bash-specific extensions are marked as such.

注意:以下适用于所有兼容 POSIX 的 shell;bash-特定的扩展被标记为这样。

A shellvariableis a shell-specific construct that is limited to the shell that defines it (with the exception of subshells, which get their own copiesof the current shell's variables),
whereas an environmentvariableis inherited by any child processcreated by the current process (shell), whether that child process is itself a shell or not.
Note that all-uppercase variable names should only be used for environmentvariables.

一个外壳变量是一个shell特定的结构,仅限于外壳定义它(有例外子shell,其中获得自己的副本当前shell的变量),
而一个环境变量被继承任何子进程被创建当前进程(shell),无论该子进程本身是否是一个shell。
请注意,全大写的变量名只能用于环境变量

Either way, a child process only ever inherits copiesof variables, whose modification (by the child) does notaffect the parent.

无论哪种方式,一个子进程永远只能继承副本的变量,其修饰(根据孩子)并不会影响

  • All environmentvariables are alsoshellvariables(the shell ensures that),
  • but the inverse is NOT true: shellvariables are NOT environment variables, unless explicitly designated or inherited as such- this designation is called exporting.
    • note that the off-by-default -ashell option (set with set -a, or passed to the shell itself as a command-line option) can be used to auto-exportall shell variables.
  • 所有环境变量也是外壳变量(外壳确保),
  • 反之则不然shell变量不是环境变量,除非明确指定或继承这样的变量- 这种指定称为exporting
    • 请注意,默认关闭的-ashell 选项(使用 设置set -a,或作为命令行选项传递给 shell 本身)可用于自动导出所有 shell 变量。

Thus,

因此,

  • any variables you create implicitlyby assignment - e.g., TSAN_OPTIONS="suppressions=/somewhere/file"- are ONLY shell variables, but NOT ALSO environment variables,
  • EXCEPT - perhaps confusingly - when prepended directly to a command- e.g. TSAN_OPTIONS="suppressions=/somewhere/file" ./myprogram- in which case they are ONLY environmentvariables, only in effect for THAT COMMAND.
    • This is what Etan's answer describes.
  • 您通过赋值隐式创建的任何变量- 例如,TSAN_OPTIONS="suppressions=/somewhere/file"- 只是 shell 变量,但不是环境变量,
  • 除了 - 可能令人困惑 -当直接添加到命令之前- 例如TSAN_OPTIONS="suppressions=/somewhere/file" ./myprogram- 在这种情况下,它们只是环境变量,仅对 THAT COMMAND 有效
    • 这就是 Etan 的回答所描述的。


Shell variables become environment variables as wellunder the following circumstances:

在以下情况下,Shell 变量也会成为环境变量:

  • based on environment variables that the shell itself inherited, such as $HOME
  • shell variables created explicitly with export varName[=value]or, in bash, also with declare -x varName[=value]
    • by contrast, in bash, using declarewithout -x, or using localin a function, creates mere shellvariables
  • shell variables created implicitly while the off-by-default -ashell option is in effect (with limited exceptions)
  • 基于shell本身继承的环境变量,例如 $HOME
  • 显式创建的 shell 变量export varName[=value]或,在bash,也与declare -x varName[=value]
    • 相比之下, in bash、 using declarewithout-x或 usinglocal在函数中,只会创建shell变量
  • 在默认情况下关闭的-ashell 选项生效时隐式创建的 shell 变量(有限的例外)

Once a shell variable is marked as exported- i.e., marked as an environment variable - any subsequent changes to the shell variable update the environment variable as well; e.g.:

一旦 shell 变量被标记为导出——即,标记为环境变量——对 shell 变量的任何后续更改也会更新环境变量;例如:

export TSAN_OPTIONS  # creates shell variable *and* corresponding environment variable

# ...

TSAN_OPTIONS="suppressions=/somewhere/file" # updates *both* the shell and env. var.


  • export -pprints all environment variables
  • unset [-v] MYVARundefines shell variable $MYVARand also removes it as an environment variable, if applicable.
  • in bash:
    • You can "unexport" a given variable without also undefining it as a shellvariable with export -n MYVAR- this removes MYVARfrom the environment, but retains its current value as a shellvariable.
    • declare -p MYVARprints variable $MYVAR's current value along with its attributes; if the output starts with declare -x, $MYVARis exported (is an environment variable)
  • export -p打印所有环境变量
  • unset [-v] MYVAR$MYVAR取消定义 shell 变量并将其作为环境变量删除(如果适用)。
  • bash
    • 您可以“取消导出”给定变量,而无需将其取消定义为shell变量export -n MYVAR- 这会MYVAR从环境中删除,但保留其当前值作为shell变量。
    • declare -p MYVAR打印变量$MYVAR的当前值及其属性;如果输出以 开头declare -x$MYVAR则导出(是环境变量)