LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
LinkBack Search this Thread
Old 05-24-2010, 01:52 AM   #1
George2
Member
 
Registered: Oct 2003
Posts: 354

Rep: Reputation: 30
environment variable issue in shell


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,

Code:
    $ 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,
George
 
Old 05-24-2010, 02:53 AM   #2
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,950
Blog Entries: 11

Rep: Reputation: 860Reputation: 860Reputation: 860Reputation: 860Reputation: 860Reputation: 860Reputation: 860
echo, in this case, is a shell built-in.
 
Old 05-24-2010, 02:58 AM   #3
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,520
Blog Entries: 27

Rep: Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174
The current shell expands "Hello [$var1]" to 'Hello [123]' before calling echo so it does not matter that $var1 is not an environment variable (regardless of whether echo is a bash builtin or not -- you could use /bin/echo and the effect would be the same).
 
Old 05-24-2010, 03:06 AM   #4
unSpawn
Moderator
 
Registered: May 2001
Posts: 26,539
Blog Entries: 51

Rep: Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604Reputation: 2604
IMO easiest displayed this way:
Code:
 ~]$ /bin/bash
 ~]$ var1=123
 ~]$ echo "Hello [$var1] ($$, $PPID)"
Hello [123] (4300, 4298)
 ~]$ /bin/bash
 ~]$ echo "Hello [$var1] ($$, $PPID)"
Hello [] (4342, 4300)
 ~]$
Notice the parent Id (PPID) of the second shell invocation is the first shell ($$).
 
Old 05-24-2010, 03:39 AM   #5
George2
Member
 
Registered: Oct 2003
Posts: 354

Original Poster
Rep: Reputation: 30
Thanks Tinkster,

Quote:
Originally Posted by Tinkster View Post
echo, in this case, is a shell built-in.
So, in this case, echo is "current" (since shell built-in), not a child environment?

Could you summarize what kinds of things are treated as child environment (I know script and executables are treated as child environment, not sure anything else?. e.g. is command "mkdir" treated as child?)
 
Old 05-24-2010, 03:40 AM   #6
George2
Member
 
Registered: Oct 2003
Posts: 354

Original Poster
Rep: Reputation: 30
I am interested in the operation of "expand". In what situations will expand happen? In any situations when variable name is replaced with its actual value will be called "expand"?

Quote:
Originally Posted by catkin View Post
The current shell expands "Hello [$var1]" to 'Hello [123]' before calling echo so it does not matter that $var1 is not an environment variable (regardless of whether echo is a bash builtin or not -- you could use /bin/echo and the effect would be the same).

Last edited by George2; 05-24-2010 at 03:41 AM.
 
Old 05-24-2010, 03:45 AM   #7
George2
Member
 
Registered: Oct 2003
Posts: 354

Original Poster
Rep: Reputation: 30
"Notice the parent Id (PPID) of the second shell invocation is the first shell ($$)." -- what do you want to prove?

Quote:
Originally Posted by unSpawn View Post
IMO easiest displayed this way:
Code:
 ~]$ /bin/bash
 ~]$ var1=123
 ~]$ echo "Hello [$var1] ($$, $PPID)"
Hello [123] (4300, 4298)
 ~]$ /bin/bash
 ~]$ echo "Hello [$var1] ($$, $PPID)"
Hello [] (4342, 4300)
 ~]$
Notice the parent Id (PPID) of the second shell invocation is the first shell ($$).
 
Old 05-24-2010, 03:46 AM   #8
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,520
Blog Entries: 27

Rep: Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174
Quote:
Originally Posted by George2 View Post
So, in this case, echo is "current" (since shell built-in), not a child environment?
It does not matter whether the command will be run in a child process or not. The key factor is that the current shell builds the command line including replacing variable references with the values of those variables as explained in my earlier post.

If there is anything about my earlier post that you did not understand please ask because when you have understood it your question will be answered -- as it would when you understand why there is nothing in the [] in unSpawn's example output Hello [] (4342, 4300).

EDIT: had not seen your post asking about expansion when writing this.

Last edited by catkin; 05-24-2010 at 03:47 AM.
 
1 members found this post helpful.
Old 05-24-2010, 03:50 AM   #9
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Córdoba (Spain)
Distribution: Gentoo
Posts: 4,029

Rep: Reputation: 368Reputation: 368Reputation: 368Reputation: 368
Quote:
Originally Posted by George2 View Post
Thanks Tinkster,



So, in this case, echo is "current" (since shell built-in), not a child environment?

Could you summarize what kinds of things are treated as child environment (I know script and executables are treated as child environment, not sure anything else?. e.g. is command "mkdir" treated as child?)
A new environment is a new shell instance. Scripts are not ran using the kernel elf (or any other) loader. When you call a script linux looks the first line for a magic number (#!), if found then it looks after that for an interpreter, which can be the name of a shell or any other kind of interpreter (perl, python, awk...) and if none is found it uses the default shell, which is open as a non-interactive non-login shell, with a new environment on its own, then the commands are dumped in that new shell and the script runs.

Whether the env of the parent shell will be passed will depend entirely on how the parent and new shell interact with each other. There's nothing magic about the "export" command. It just marks a var in a special way, but whether it will be available on the child shell is entirely up to that shell and how did you invoke it.

The fact that echo is a builtin has nothing to do with the issue as said before. How expansion takes place is also up to the shell you use, you should be checking the man page for your shell to know about that, there are many kinds of expansion, not just var expansion. But in any case, the expansion always takes place before anything else happens. So, the "echo" tool (it doesn't matter builtin or external) doesn't ever see "$var" as a variable, it sees the contents of $var which is what the current shell will expand $var to before echo is even called.
 
1 members found this post helpful.
Old 05-24-2010, 03:50 AM   #10
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,520
Blog Entries: 27

Rep: Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174
Quote:
Originally Posted by George2 View Post
I am interested in the operation of "expand". In what situations will expand happen? In any situations when variable name is replaced with its actual value will be called "expand"?
Yes. For more detail (and this is crucial to getting to grips with bash programming) see Shell Operation here.
 
1 members found this post helpful.
Old 05-24-2010, 03:58 AM   #11
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,520
Blog Entries: 27

Rep: Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174
Quote:
Originally Posted by i92guboj View Post
Whether the env of the parent shell will be passed will depend entirely on how the parent and new shell interact with each other. There's nothing magic about the "export" command. It just marks a var in a special way, but whether it will be available on the child shell is entirely up to that shell and how did you invoke it.
That doesn't fit with my understanding. AFAIK environment variables are part of every process and each process inherits its parent's environment variables. It depends on the program running in the process whether it makes any use of them.

EDIT: on re-reading I now see that the two explanations are not exclusive but wouldn't all child shells have access to parent shell's envars except in when invoked via the env command with options to modify the envars?

Last edited by catkin; 05-24-2010 at 04:02 AM.
 
1 members found this post helpful.
Old 05-24-2010, 05:23 AM   #12
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Córdoba (Spain)
Distribution: Gentoo
Posts: 4,029

Rep: Reputation: 368Reputation: 368Reputation: 368Reputation: 368
Quote:
Originally Posted by catkin View Post
That doesn't fit with my understanding. AFAIK environment variables are part of every process and each process inherits its parent's environment variables. It depends on the program running in the process whether it makes any use of them.
Not really. At low level there's always a layer where this stuff takes place. In Linux that's libc (usually glibc nowadays). What part of a given process is visible to the children of this process depends on the OS. After all, vars are nothing else but data structures, and shells are nothing but regular programs at the end of the day.

In a modern OS with a minimal degree of privacy and a good memory protection model a given program (our shell in this case) should be capable of deciding what portion of its private data it wants to expose to any external entity (or even an internal one, that's the way functions or classes work in C/C++ and most programing languages).

I haven't ever dug inside the bash source code at deep level, though.

Quote:
EDIT: on re-reading I now see that the two explanations are not exclusive but wouldn't all child shells have access to parent shell's envars except in when invoked via the env command with options to modify the envars?
A simple C program can show the behavior of getenv() / environ().

Code:
#include <unistd.h>
#include <stdio.h>

int main (int argc, char *argv[]) {
  extern char **environ;
  int i = 0;

  while (environ[i] != NULL) {
    printf("%s\r\n", environ[i]);
    i++;
  }
}
This recurses the list of env variables. Save it as foo.c and compile it with this:

Code:
gcc foo.c -o foo
Now this will illustrate how variables are not necessarily exported into subprocesses (the parent can decide what data to pass, regardless what data the child will or won't use).

Code:
[jesgue] 12:19:59 $ ./foo | grep CHARLIE
[jesgue] i92guboj@jesgue:~/tmp
[jesgue] 12:20:05 $ CHARLIE=parker
[jesgue] i92guboj@jesgue:~/tmp
[jesgue] 12:20:12 $ ./foo | grep CHARLIE
[jesgue] i92guboj@jesgue:~/tmp
[jesgue] 12:20:13 $ export CHARLIE=parker
[jesgue] i92guboj@jesgue:~/tmp
[jesgue] 12:20:18 $ ./foo | grep CHARLIE
CHARLIE=parker
foo is just a regular subprocess that serves us as an example, but a new shell instance would just be another subprocess as well. This is yet another example, a very similar one to this that unSpawn already posted above.

Code:
[jesgue] i92guboj@jesgue:~
[jesgue] 12:21:14 $ echo $CHARLIE

[jesgue] i92guboj@jesgue:~
[jesgue] 12:21:21 $ CHARLIE=parker
[jesgue] i92guboj@jesgue:~
[jesgue] 12:21:40 $ echo $CHARLIE
parker
[jesgue] i92guboj@jesgue:~
[jesgue] 12:21:53 $ sh -c 'echo $CHARLIE'

[jesgue] i92guboj@jesgue:~
[jesgue] 12:21:56 $ export CHARLIE=parker
[jesgue] i92guboj@jesgue:~
[jesgue] 12:22:03 $ sh -c 'echo $CHARLIE'
parker
Change "bash" by "foo", it's all the same.
 
1 members found this post helpful.
Old 05-24-2010, 08:21 AM   #13
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,520
Blog Entries: 27

Rep: Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174Reputation: 1174
Many thanks i92guboj for that detailed information

I tried your C example (first direct C compilation in more than ten years -- you might have started something! ). I was puzzled by the need for extern char **environ;. Is it not declared in one of the include files? Following this up out of curiosity, presumably #include <unistd.h> includes /usr/include/unistd.h (there are several unistd.h files on the system) and that does declare environ as long as __USE_GNU is defined. But is __USE_GNU defined and where? Perhaps it's a default when using gcc ... ?

Of course it is only the envars which are available to the new program running in the child process; the private data is lost when the execve(2) system call loads the new program with its new data section.

AIUI a Linux process can be thought of as having two parts. One holds process attributes such as open file descriptors, security settings, the command line ... and the envars. The other is the program and its data. The execve(2) system call replaces the program and its data but does not change the other part, including the envars -- unless a non-NULL envp is given in which case a new set of envars is loaded from private storage. On the evidence before us, if bash does use a non-NULL envp, it copies its envars from private storage.

Based on the above theorising, the env of the parent (bash) shell will be passed to a new shell. The "export" command creates variables which are available to child shells as envars. Thus the shell's envars are available to the child shell unless it is invoked via the env command with options to change the envars. AFAIK all (?) shells do use them.
 
1 members found this post helpful.
Old 05-27-2010, 11:24 AM   #14
George2
Member
 
Registered: Oct 2003
Posts: 354

Original Poster
Rep: Reputation: 30
Thanks i92guboj!

Question answered!

regards,
George
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how can i change the value of a environment variable through shell script ? manomohan Programming 8 02-11-2010 09:55 PM
shell to set environment variable ufmale Linux - Newbie 5 11-16-2009 11:35 AM
what is the difference between CGI and SHELL environment variable cnsung Linux - Server 3 09-11-2009 10:36 AM
Global (shell) environment variable question Seventh Linux - Newbie 1 04-05-2007 03:18 PM
how to set the Environment variable from shell Scrit Sundaram Linux - Software 2 10-13-2006 11:59 PM


All times are GMT -5. The time now is 10:56 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration