0

Run these commands in Bash:

  1. NODE_ENV=production echo $NODE_ENV outputs ""

  2. NODE_ENV=production && echo $NODE_ENV outputs "production"

  3. export NODE_ENV=production && echo $NODE_ENV outputs "production"

Now there is a file index.js:

console.log(process.env.NODE_ENV)

then run these commands in Bash:

  1. NODE_ENV=production node index.js outputs "production"

  2. NODE_ENV=production && node index.js outputs "undefined"

  3. export NODE_ENV=production && node index.js outputs "production"

I get confused by these commands, why are the results different?

Edit:

Thanks everyone. Now I give my explanations, maybe it's helpful for other guys.

NODE_ENV=production echo $NODE_ENV, Bash expends $NODE_ENV before running this command, at this point $NODE_ENV is not set so the result is blank.

NODE_ENV=production && echo $NODE_ENV, these are two commands, the second command command only runs if the first command succeeds. Before running the second command Bash expends $NODE_ENV which is set at this point.

NODE_ENV=production node index.js, prefixing a variable definition to a command makes this variable available to this command.

NODE_ENV=production && node index.js, node is an external commands, Bash forks it and runs it in a sub-process, node doesn't get $NODE_ENV from parent process.

export NODE_ENV=production && node index.js, export makes the variable available to sub-processes, so node gets $NODE_ENV.

Ivan Yan
  • 475
  • 6
  • 8
  • 1
    Related: [specifying environment variables for echo on command line?](http://stackoverflow.com/questions/10938483/bash-specifying-environment-variables-for-echo-on-command-line) – Jonathan Lonowski Apr 26 '16 at 01:27

1 Answers1

2

Few points first:

  • && is a logical operator that separates two commands (the second one runs only if the first one succeeds)

  • For var=value some_command, the variable var is passed to the environment of some_command, only after shell performs all expansions on some_command

Now:

  • NODE_ENV=production echo $NODE_ENV: shell runs echo $NODE_ENV first and NODE_ENV is unset while running and hence the output is blank; the variable NODE_ENV=production can only be passed to the expanded environment like i told earlier

  • NODE_ENV=production && echo $NODE_ENV has two commands; as the declaration comes in the first (and succeeds) and hence NODE_ENV will have the value production in the second command. Note that, the variable NODE_ENV will not be passed to the expanded environment of the second command.

  • export NODE_ENV=production && echo $NODE_ENV is like the above with the fact that you are making NODE_ENV available throughout the environment (all subprocesses) by exporting-ing. Hence the variable will be available to the second command in the expansion time and also to its environment.

Similar logics apply to the node commands (and all other alike cases) too.

heemayl
  • 39,294
  • 7
  • 70
  • 76
  • I'm not sure your first bullet point is entirely accurate. The environment variable `NODE_ENV` is indeed set to `production` while the `echo` is running... it's just that that variable isn't used in expanding its command line, and so has no effective impact on output. – Charles Duffy Apr 26 '16 at 01:38
  • ...this is pertinent when you have environment variables like `POSIXLY_CORRECT` that (for some implementations) can change how `echo` itself behaves. – Charles Duffy Apr 26 '16 at 01:39
  • Charles, so the command exists in the environment but its usage depends on the variable itself? – heemayl Apr 26 '16 at 01:54
  • I'm not sure exactly what you mean by that comment. Expanding parameters, as you know, happens before per-command environment variables are applied -- but those variables *are* still applied, and some values can/will change how commands behave at runtime. (If one wants to use environment variable names that one is assured won't change commands' behavior, the set of variable names with at least one lower-case character is reserved for this purpose). – Charles Duffy Apr 26 '16 at 03:17
  • ...see http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html for the standards document establishing that convention. – Charles Duffy Apr 26 '16 at 03:17
  • As an easy example that works even on non-GNU systems [subject to the following caveat about localizations available]: `LANG=ja echo hello >&-` will, if your system has the appropriate translation table installed, emit a different error message than `LANG=en echo hello >&-` (both fail because stdout is to a closed file). – Charles Duffy Apr 26 '16 at 03:20
  • @CharlesDuffy, I have just added my explanations to the question description, could you help to check it ? – Ivan Yan Apr 26 '16 at 03:56
  • @IvanYan, answers should be added as answers, not as question edits. If the existing answers aren't sufficient, you're welcome to add your own. – Charles Duffy Apr 26 '16 at 03:57
  • @IvanYan, ...that said, reading those explanations, they are indeed correct. – Charles Duffy Apr 26 '16 at 03:58
  • @CharlesDuffy, this question is marked as duplicate, I could not add an answer... – Ivan Yan Apr 26 '16 at 04:27