Why does FOO=bar; export the variable into my environment
No, FOO=bar; does not export the variable into my environment
A var is set in the (present) environment only if it was previously exported:
$ export foo
$ foo=bar
$ env | grep foo
foo=bar
A variable is set in the environment of a command when it is placed before the command. Like foo=bar command
. And it only exists while the command runs.
$ foo=bar bash -c 'echo "foo is = $foo"'
foo is = bar
The var is not set for the command line (in the present shell):
$ foo=bar bash -c echo\ $foo
Above, the value of $foo
is replaced with nothing by the present running shell, thus: no output.
Your command:
$ FOO=bar docker run -it -e FOO=$FOO debian env
is converted to the actual string:
$ FOO=bar docker run -it -e FOO= debian env
by the present running shell.
If, instead, you set the variable (in the present running shell) with foo=bar
before running the command, the line will be converted to:
$ FOO=bar; docker run -it -e FOO=bar debian env
A variable set to the environment of a command is erased when the command returns:
$ foo=bar bash -c 'echo'; echo "foo was erased: \"$foo\""
Except when the command is a builtin in some conditions/shells:
$ ksh -c 'foo=bar typeset baz=quuz; echo $foo'
bar
There are a number of variations to consider:
Just doing
FOO=bar
creates a variable namedFOO
with valuebar
, but that variable isn't passed along to new processes:$ echo $FOO $ FOO=bar $ echo $FOO bar $ bash # Start a new bash process $ echo $FOO # Variable is not set in the new process $ exit # Exit new bash process
Running
FOO=bar <command>
will run the given command with the variable set (but doesn't affect the original shell's environment):$ echo $foo $ FOO=baz bash # start a new bash process $ echo $FOO baz $ exit # exit the new bash process exit $ echo $FOO # No FOO in the original bash process $
Doing
FOO=foo; <command>
is equivalent to (1); putting a semicolon between two commands is equivalent to running those two commands on two separate lines:$ FOO=foo; echo $FOO foo $ bash $ echo $FOO $ exit exit $ echo $FOO foo $
Using
export
will pass a variable in the shell's environment to newly-created processes:$ export FOO=bar $ echo $FOO # Value set in original shell bar $ bash # Start another shell $ echo $FOO bar # Value was passed along to new process $ exit exit
FOO=bar docker run -it -e FOO=$FOO debian env
Here the $FOO
from FOO=$FOO
will be expanded before the FOO=bar
assignment happens.
You can check that with a more straight-forward example:
FOO=first
FOO=second echo FOO=$FOO
=> FOO=first
FOO=third; echo FOO=$FOO
=> FOO=third
The FOO=bar cmd
form will really set FOO=bar
in the environment of cmd
, but a command like docker
does not automatically export its own environment into the container, but the environment vars have to be added explicitly with the -e
switch.
Again, a more straightforward demo would be:
FOO=before
FOO=after env - FOO=$FOO printenv FOO
=> before