environment variable issue in shell

1

1

I am using Red Hat Linux Enterprise 5. I know the theory that -- using export to set environment variable, the environment variable will apply to current and child environment, but without using export to set environment variable, the environment variable will only apply to the current environment.

My confusion is, what is the exact definition of "child environment" and "current environment"? For example,

$ var1=123
$ echo "Hello [$var1]"

the value of var1 (which is 123) is printed in shell, but I think echo is a command invoked by current shell, and it (the echo command) should be a child environment of current shell and the value of var1 should not (because not using export var1=123) impact echo. Any comments?

Thanks in advance!

George2

Posted 2010-05-22T10:48:27.817

Reputation: 4 239

Answers

3

The variable is expanded in the current environment.

$ set -x    # turn on tracing
$ var1=123
+ var1=123
$ echo "Hello [$var1]"
+ echo 'Hello [123]'
Hello [123]
$ set +x

As you can see from the trace (the lines beginning with "+"), echo sees "Hello [123]". It never gets the variable.

As you saw from gogiel's answer to your other question, exported environment variables do affect the environment of the child:

$ echo $LANG
en_US.UTF-8
$ declare -p LANG   # the response includes "-x" which shows the variable is already marked for export
declare -x LANG="en_US.UTF-8"
$ ls --help | head -n 4
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort.
$ LANG=es_MX.utf8 ls --help | head -n 4
Uso: ls [OPCIÓN]... [FICHERO]...
Muestra información acerca de los ARCHIVOS (del directorio actual por defecto).
Ordena las entradas alfabéticamente si no se especifica ninguna de las opciones -cftuSUX ni --sort.

Or I could have set the value of LANG in the current environment and since it's exported it would be inherited by the child environment:

$ LANG=es_MX.utf8
$ grep --help | head -n 4
Modo de empleo: grep [OPCIÓN]... PATRÓN [FICHERO]...
Busca un PATRÓN en algún ARCHIVO o entrada estándar.
PATTERN es, por omisión, una expresión regular básica (BRE).
Ejemplo: grep -i '¡Hola, mundo!' menu.h main.c
$ sed --help | head -n 4
Uso: sed [OPCIÓN]... {guión-sólo-si-no-hay-otro-guión} [fichero-entrada]...

  -n, --quiet, --silent
                 suprime la muestra automática del espacio de patrones
$ while [[ = 4 ]]    # create an error on purpose to show Spanish error message
bash: se esperaba un operador binario condicional
bash: error sintáctico cerca de `4'

Edit:

Here is a simple script (let's call it showvars) so you can see what's going on both inside and outside.

#!/bin/bash
arguments="$@"
printf "The script has started.\n"
printf "These are the parameters passed to the script: [$arguments]\n"
scriptvar=100
printf "This is the value of scriptvar: [$scriptvar]\n"
printf "This is the value of exportvar: [$exportvar]\n"
printf "This is the value of shellvar: [$shellvar]\n"
printf "This is the value of commandvar: [$commandvar]\n"
printf "The script has ended.\n"

Now we do these steps at a shell prompt:

$ shellvar=200
$ export exportvar=300
$ ./showvars 400 $shellvar 500
The script has started.
These are the parameters passed to the script: [400 200 500]
This is the value of scriptvar: [100]
This is the value of exportvar: [300]
This is the value of shellvar: []
This is the value of commandvar: []
The script has ended.
$ commandvar=600 ./showvars 400 $shellvar 500
The script has started.
These are the parameters passed to the script: [400 200 500]
This is the value of scriptvar: [100]
This is the value of exportvar: [300]
This is the value of shellvar: []
This is the value of commandvar: [600]
The script has ended.
$ printf "This is the value of commandvar: [$commandvar]\n"
This is the value of commandvar: []
$ commandvar=600
$ ./showvars 400 $shellvar 500
The script has started.
These are the parameters passed to the script: [400 200 500]
This is the value of scriptvar: [100]
This is the value of exportvar: [300]
This is the value of shellvar: []
This is the value of commandvar: []
The script has ended.
$ printf "This is the value of scriptvar: [$scriptvar]\n"
This is the value of scriptvar: []
$ printf "This is the value of exportvar: [$exportvar]\n"
This is the value of exportvar: [300]
$ printf "This is the value of shellvar: [$shellvar]\n"
This is the value of shellvar: [200]
$ printf "This is the value of commandvar: [$commandvar]\n"
This is the value of commandvar: [600]

As you can see shellvar is not available inside the script and scriptvar is not available outside it. Since exportvar is exported, it's available both inside and outside the script. And commandvar is only available inside the script when it's passed on the command line when calling the script. If it's set in the interactive environment and then the script is called, it's available only in the interactive environment.

Paused until further notice.

Posted 2010-05-22T10:48:27.817

Reputation: 86 075

Why you say "sees "Hello [123]". It never gets the variable"? It is obvious that variable value 123 is taken by this statement and Hello [123] is printed, other than Hello[]? Any comments? – George2 – 2010-05-22T16:34:45.003

1Yes, the variable is expanded by the shell (it replaces the variable with its value) and the value is passed to echo. So echo never sees the variable, just its value. – Paused until further notice. – 2010-05-22T17:36:13.137

Hi Dennis, sorry for my confusion again. I think if we do not use export, then the variable value can not be seen from child environment, correct? I think command like ls and echo are child environment (which is command executed/invoked by current shell), so in your sample you set var1 without export, command like echo or ls should not know its value (which is 123), why in your sample, echo (as a child environment of current shell) knows the value 123? Please correct me for anything wrong. Have a nice weekend! – George2 – 2010-05-23T14:07:26.207

1@George2: Look at the trace at the top of my answer. The "$" is the shell prompt. I type echo "Hello [$var1]" and the next line (that starts with "+") shows what actually happens. The shell (Bash) tells echo to output "123". The shell replaces the name of the variable with its value before it gives it to echo so echo never sees the variable it only sees the value passed as a parameter. I'm going to add a small script to my answer that will show what's going on by letting you see inside the process. It will take me a few minutes, so check back if it's not there yet. – Paused until further notice. – 2010-05-23T14:27:27.310

Thanks Dennis, your reply is so informative! Almost all of my confusions are resolved. The last question, about variable which is using export to set. Normally it will impact not only current shell, but also sub-environment like script/executable invoked by current shell. Besides script/executable, any other entities which will be impacted the same way as script/executable? I am also not sure whether shell command like "mkdir" will be treated as sub-environments as well? – George2 – 2010-05-24T02:00:11.507

1@George2: What kind of other entities? mkdir is a child of whatever environment it's invoked from - the interactive shell or a script, for example. Usually such executables are only affected by exported environment variables that are documented in their man pages. The one type of environment variable that is often effective even though it's not documented in individual man pages is the set of locale related variables such as LANG demonstrated in some of the examples above. – Paused until further notice. – 2010-05-24T03:46:50.357

"mkdir is a child of whatever environment it's invoked from" -- my confusion is what kinds of things on Linux are child, I know executables, scripts are child. But I am not sure whether command like mkdir is a child of current environment or not? Is command like echo also child of current environment? – George2 – 2010-05-24T05:33:43.533

1executables, scripts, commands, yes. – Paused until further notice. – 2010-05-24T11:17:20.227

but echo is an exception? It is a command but can receive variable value from parent shell? – George2 – 2010-05-25T07:47:36.570

1No, not an exception. Look at file="/etc/passwd"; ls -l "$file" Here ls is receiving a variable's value from the parent shell. The value not the variable itself. – Paused until further notice. – 2010-05-25T08:04:05.483