Why do I have to `source .profile` in every terminal I open?

When we change some variable in ~/.profile in Ubuntu, then we execute the command source .profile. Then the change is effective only in this terminal. If we open a new terminal we have to execute the command source .profile again. So it seems that different terminals have their own environment though they may belong to the same user.

What is the advantage of making every terminal have its own environment path? It seems that it would be better if different terminal which belonged to the same user shared the same environment variable.


Solution 1:

The reason for this is that ~/.profile is only sourced by login shells. When you open a new terminal window, the shell that starts is a non-login shell by default. If you log out, and log back in, the change to ~/.profile will be effective in all your terminals, because ~/.profile is sourced when you log in to your session.

It's not the case that different terminal windows have a different environment, but that sourcing ~/.profile only executes ~/.profile in the current shell (that's exactly what the source command does).

By contrast, a change to ~/.bashrc will immediately affect any new terminal window you open, or any Bash shell you start by typing bash, because it is sourced by all interactive Bash shells.

Solution 2:

Environment variables are not just for user preferences. They're a generic mechanism for communicating a variety of setting information from a parent process to child processes it starts.

There are numerous cases where a process will set specific environment variables in order to influence just processes it starts. For example, a script may deliberately reset the locale settings for commands it starts, such that it can parse output from them. The build scripts for many large software packages use nested invocations of make that coordinate with each other through environment variables. Specialized tools may need to change the working conditions of other programs they start by doing tricks with $LD_PRELOAD or $PATH.

If something a user does in a different window while a long compilation is running in another would just magically change the environment variables of all his processes behind their backs, madness and chaos would result.

Other environment variables contain information about the particular session a process is started in. Programs expect $TERM to describe the command set of the particular terminal (or terminal emulator) they are connected to; making that a general per-user setting would make it impossible to be logged into the same system with several different kinds of terminals. Even if you only have one piece of terminal hardware and never log in remotely, programs such as screen depend on setting a different $TERM for the processes that run inside their session.

A better question would be, why do we use a process-to-subprocess communication mechanism for user preference settings, rather than a per-user database?

Answer: Because it works well enough and the benefits of making a per-user database are not large enough that the work of changing everything to use that instead of environment variables would be done.

(I can think of very few preference settings where there wouldn't be some use cases where it's convenient to change them just for executing a single script, for example. So in order not to lose functionality, everything would still need to be overridable by environment variables, which results in added complexity and more confused users).

It's not as if alternatives don't exist. For example, X resources are per display session rather than per process. But they are difficult to access for command-line programs -- and command-line programs usually need to work for remote logins that don't even have an X server to connect to.