The shell is the command line interpreter that translates commands entered by a user into actions to be performed by the operating system. The shell could be started in interactive way (where the user can type and execute commands) or in non interactive way (forked by script or program like crontab, etc.).
The interactive shells are started within a terminal emulator, which refers to a GUI applications as gnome-terminal, xterm, etc., or within TTY which refers to a virtual text console. The TTYs are accessible by the key combination Ctrl Alt F1-9. In the desktop distributions of Linux, the desktop environment is running within one of these TTYs.
References:
No matter it is terminal emulator or TTY you are capable to do the same things with the shell running inside.
The default user's shell in Ubuntu is Bash. There is an initialization file called .bashrc
which is located in the user's home directory. This file (along with some other system initialization files as /etc/bash.bashrc
) is sourced when the user opens a new interactive shell. Thus the user's default environment is created.
Literally by sourcing .bashrc
some of the environment variables get certain values. Such environment variables are:
$PATH
which contains column separated system paths where the executable files could be found,
$PS1
which determines how your prompt looks like, e.g.: user@host:/current/directory$,
$LANG
which sets the default locale, or $LC_ALL
which overrides all locale settings (source of this explanation, read more at man locale
).
So if you want to permanently change some environment variable (within the user's Bash shell) you can modify (or set) its value within .bashrc
. Otherwise, the change will only be valid for the current instance of the shell.
For example, open a new terminal and type PS1='prompt_changed->'
and your prompt will be changed to that string. Then keep that terminal window open and open a new terminal - you will see this change is not applied there. To recover the first terminal you can source manually the .bashrc
file by the command . ~/.bashrc
.
When you use the export
command you are exporting a variable to the subshells that are forked from the current shell (child shells), not to the other (siblings) shells created by the parent processes of the current shell. Here is an example:
user@host:~$ VAR='Hello!' # Define a variable called VAR
user@host:~$ echo $VAR # Output the value of the variable
Hello!
user@host:~$ export VAR # Export the variable
user@host:~$ bash # Fork new bash shell
user@host:~$ echo $VAR # Output the value of the exported variable
Hello!
user@host:~$ exit # Exit to the parent shell
user@host:~$ sh # Fork new sh (dash) shell
$ echo $VAR # Output the value of the exported variable
Hello!
The command env
is used to change the environment of a command or script execution. Here are a few lines from man env
:
env
- set the environment for a command invocation. The env
utility shall obtain the current environment, modify
it according to its arguments, then invoke the utility named by
the utility operand with the modified environment.
-i
Invoke utility with exactly the environment specified by the arguments; the inherited environment shall be ignored completely.
The following command: env -i PATH=/mybin mygrep xyz myfile
invokes the command mygrep
with a new PATH
value as the only entry in its environment. In this case, PATH
is used to locate mygrep
, which then must reside in /mybin
.
env
is often used at the beginning of the scripts (within the so-called shebang) to increase their portability. Here are two topics that cover this usage:
When run without arguments, the env
command outputs a list of the environment variables.
Once again, the .bashrc
file in the home directory customizes features of the shell, such as creating or modifying variables and aliases, and defining functions.
Fore example, let's define the following function at the bottom of the .bashrc
file.
hello() { echo "Hello, ${USER^}!"; }
After saving the file you could source it or open a new terminal instance and type hello
.
spas@host:~$ hello
Hello, Spas!
So we can see this function (or variable or alias) is available within the current shell. At this stage it is called local function (or variable or alias), so if we inspect the environment by env | grep hello
our function won't be there.
Local variables exist only in the current shell, and cannot affect other commands or applications.
After defining a function (variable, alias) in .bashrc
we can export it in order to make it available for the sub shells (commands or scripts) forked from the current shell - thus it become global or environment function (variable, alias).
hello() { echo "Hello, ${USER^}!"; }
export -f hello
spas@host:~$ source ~/.bashrc # in bash 'source' is synopsis to '.'
spas@host:~$ env | grep 'hello' # parse 'hello' within the output of 'env'
BASH_FUNC_hello%%=() { echo "Hello, ${USER^}!"
spas@host:~$ bash -c 'hello' # fork an non interactive sub shell
Hello, Spas! # and execute the function inside
Keep in mind the non interactive shells, in most cases, doesn't source by default the initialization files as .bashrc
, so their environment is limited than the environment of the interactive shells.
For example when you design a script that will be used by crontab you must use full paths to the commands or make sure it has the necessary environment.