Disclaimer: Using bash.
I just need some confirmation / correction on my understanding of these things:
-
env
is basically displaying the current environmental variables that are accessible to my current session AND any child sessions (such as if I were tobash
into a child session). -
If I were to set a new variable such as
MYMESSAGE="hello world!"
then it would only be visible to the session in which I created it. If I went into a child session, I would not be able to, for example,echo $MYMESSAGE
. -
I can
export MYMESSAGE="hello world!"
though to make it accessible to child sessions.export
is the same as adding it to whateverenv
is pulling up. -
However, just because you
export
something, it won't stick if you happen to close out your sessions and restart the terminal. Edit.bashrc
in your/home/username/
directory and add any new environmental variables there, since this script is run on login.
Is my understanding correct so far?
Furthermore, I don't fully understand where the details of env
comes from. Is the list of environmental variables all stored in some file and then edited/appended to by .bashrc
? I'm just trying to understand how all of this works.
Best Answer
You basically got it right, however a few extra points...
There are several "start-up files" bash may run - some for backwards compatibility with the bourne-shell (sh), other depending on how you started bash: Did you log-in to X? Did you log-in to a TTY? Did you start
bash
in another (bash-)shell? Is bash running as a script (non-interactive)? Thus .bashrc is not always run, nor may it be the only start-up file. However, it's a good idea to "source" (read and execute) .bashrc in the other start-up files too, so the content of your .bashrc is always added. Useman bash
and look especially on the part about how bash starts... the FILES-section also list the files bash uses, including all start-up files. For a more in-depth, tryinfo bash
.In addition to you own start-up files, there are corresponding "default" global start-up files in /etc - these are typically read/executed by
bash
before your own start-up files. There also other programs that defines their own environment-variables in addition to those defined by bash,which may complement or even override those set by bash. Of particular note is X (the GUI), since it will set-up two different sets of environments, depending on whether X is started manually (withxinit
orstartx
) from a VT, or is started by a "display manager" (eg.xdm
orkdm
) so you can log-in directly into X (X is started when you boot, and you got a dialog-box for username/password in X).But before
bash
,X
or any other programs starts, much of the environment - environment-variables - you'll be using, will have been set-up, for example by thelogin
command. Much of this you can find in /etc/login.defs and other configuration-files. For example, the PATH-variable will be set-up - and will differ depending on whether you're root or a normal user.So if you look at the various files and scripts that are ran as part of the boot, init and log-in process; you'll find most of all the variables you can list with
env
. Some however - likeCWD
(current working directory) - are set (and updated) automatically by the shell (bash) itself.When you run a command, what happen is that bash use a system call called fork().
bash
basically makes an identical copy of itself, with the exception that the child gets a new PID (Process ID) and that it's PPID (Parent PID) is that of it's "mother". Else they're identical - even including the environment-variables... assuming the variable in question was made inheritable by firstexport
ing it. You now got two copies ofbash
. Then another system-call -exec() - is used, which basically replaces the bash-program "in memory" for the child bash-process, with another program - for example withls
,ps
ormutt
(whatever you typed)... but the environment-variables remains, so the new program inherits it's environment frombash
. This child now controls your terminal (unless you put the command in the background with &) until it terminates, while your original bash-shell (basically) sleeps. When the command terminates, you return to your originalbash
-shell, which is ready for another command.