bash is a powerful and versatile command line shell. It can be used to run commands, create files, and access system resources. However, there are a few environment variables that can help you more easily control your bash sessions. Here is a complete guide to understanding and using bash environment variables:
- The Bourne Shell Environment Variable The Bourne shell is the default shell used by most Linux systems. It has a simple syntax and is easy to learn. The Bourne shell environment variable is named BASH_ENV . It contains the following values: BASH_ENV= “HOME=/home/username/.bash” BASH_ENV= “PATH=/usr/local/bin:/usr/sbin:/usr/bin:/usr/games” BASH_ENV= “PWD=/home/username/.bash”
- The Bash Variables in Your Home Directory If you are using Ubuntu or Debian systems, you should set up your home directory before starting your bash session. This will make it easier for you to find and use the Bash variables in your home directory. To do this, open Terminal and type: mkdir -p ~/.bashrc . Once you have created ~/.bashrc , open it in a text editor such as Notepad or Emacs (if you are using GNU Emacs). In ~/.bashrc , add the following lines: export BASH_ENV=“HOME=/home/username/.bash” export PATH="$PATH:/usr/local/bin:/usr/sbin:/usr/bin:/usr/games" export PWD="/home/$USER/.bash"
They are either environmental or shell variables by convention. Both of which are usually defined using all capital letters. This helps users distinguish environmental variables from within other contexts.
1 – Terminology
As said there are technically one of two categories a variable can fall into:
1 – Terminology2 – Displaying Variables3 – Variable Definitions4 – Setting Variables5 – Demoting and Unsetting Variables6 – Persistent Variables
“Environment variables” have been defined for use in the current shell and will be inherited by any child shells or processes spawned as a result of the parent. Environmental variables can also be used to pass information into processes that are spawned by the shell.
“Shell variables” are contained exclusively within the shell in which they were set or defined. They are mostly used to keep track of ephemeral temporal data, like the current working directory in a session.
2 – Displaying Variables
To see all currently set environment variables in a terminal type:
[alert-announce]
$ printenv
[/alert-announce]
Alternatively the shorter command env works too:
[alert-announce]
$ env
[/alert-announce]
To see an individual or specific environment variables and print with standard output use either of the following:
[alert-announce]
$ printenv TERM
[/alert-announce]
Prints multiple variables.
[alert-announce]
$ printenv SHELL USER
[/alert-announce]
echo prints contents.
[alert-announce]
$ echo $TERM
[/alert-announce]
Which can print multiple variables too.
[alert-announce]
$ echo $LANG $HOME
[/alert-announce]
To output shell variables as well as environment variables using set do the following:
[alert-announce]
$ set | less -N
[/alert-announce]
set is usually used to change or unset shell options and parameters but here we have piped the command through less to see what it outputs instead of allowing it to make changes.
The command can be modified to not show the residual bash functions included in the last output (using posix mode). The brackets also indicate that the process will be run in a sub shell so that set does not actually change anything in the current shell’s environment.
[alert-announce]
$ (set -o posix; set) | less -N
[/alert-announce]
Note that there is no one command for retrieving only what we class as shell variables. One way of getting these as output is with a sorted comparison from both of the two previous set and env commands. This is not one hundred percent accurate, however.
[alert-announce]
$ comm -23 <(set -o posix; set | sort) <(env | sort) | less -N
[/alert-announce]
In the last command comm is used to compare the output of set in a sub shell with the output of env in a sub shell, before finally being fed through less . The two compared outputs are also sorted with sort .
3 – Variable Definitions
Environment Variables
SHELL – /bin/bash
This is how the system knows what shell to be used when interpreting commands. In most Linux systems Bash is the default primary shell, but many others can be installed on the system and assigned to this variable.
TERM – xterm
This specifies the type of terminal to emulate when running the shell. The default in GUI based desktop environments is often linux or xterm .
USER – scarlz
Is set to the username of the currently logged in Linux user.
PWD – /etc/apache2
Like the pwd command it contains the currently active working directory.
OLDPWD – /home/scarlz/dotfiles
The last working directory the user moved from. The shell uses this when the cd - command is invoked.
LS_COLORS – .tar=01;31:.tgz=01;31:.arj=01;31:.taz=01;31:
The ls command has built-in colour support used to differentiate between file types and folders. Colour codes are stored in this variable that determine the colours used.
PATH – /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
The shell’s main “Path” variable holds a list of directories that the system will query when looking for commands/programs the user types in. They are checked in the order listed.
LANG – en_GB.UTF-8
The currently set language and localization in use (locales), including character encoding.
HOME – /home/scarlz
The current user’s home directory.
_ – /usr/bin/printenv
The previously executed command and its path.
EDITOR – vim
The shell’s preferred text editor.
PAGER – more
The shell’s preferred pager program.
MAIL – /var/spool/mail/$LOGNAME
Contains the location of incoming email. The traditional path is used as an example here.
Shell Variables
BASHOPTS
The list of options that the shell included when bash was run. Useful for finding out if the shell environment currently can do what you expect it to.
[alert-announce]
$ echo $BASHOPTS BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob
[/alert-announce]
BASH_VERSION
The version of bash being executed, in human-readable form.
[alert-announce]
$ echo $BASH_VERSION 4. 3. 11(1)-release
[/alert-announce]
BASH_VERSINFO
Similar to the last variable except in “machine“ readable format.
[alert-announce]
$ echo $BASH_VERSINFO 4
[/alert-announce]
COLUMNS
The number of columns that are being used to draw output to the screen.
[alert-announce]
$ echo $COLUMNS 239
[/alert-announce]
DIRSTACK
The stack of directories that are available with the pushd and popd commands.
[alert-announce]
$ echo $DIRSTACK ~
[/alert-announce]
HISTFILESIZE
Number of lines of command history that gets stored to the file per bash session.
[alert-announce]
$ echo $HISTFILESIZE 2000
[/alert-announce]
HISTSIZE
The number of lines of command history maximum to be stored in memory.
[alert-announce]
$ echo $HISTSIZE 1000
[/alert-announce]
HOSTNAME
The hostname of the computer at this time.
[alert-announce]
$ echo $HOSTNAME scarlz-corsair
[/alert-announce]
IFS
The internal field separator character that separates input on the command line. By default, this is a space so there is no real output to show as an example command.
PS1
The primary command prompt’s definition. Defines quint-essentially what your prompt looks like when you start a shell session.
[alert-announce]
$ echo $PS1 [\e]0;[email protected]\h: \w\a]${debian_chroot:+($debian_chroot)}[\033[01;32m][email protected]\h[\033[00m]:[\033[01;34m]\w[\033[00m]$
[/alert-announce]
SHELLOPTS
Any shell options that can be or have been set with the set option.
[alert-announce]
$ echo $SHELLOPTS braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
[/alert-announce]
UID
The assigned UID of the current user.
[alert-announce]
$ echo $UID 1000
[/alert-announce]
4 – Setting Variables
Shell Variables
To create a shell variable in the current shell session, specify a name and a value in the same manner as usual in Bash. Adhering to the naming convention of using full capitals for the variable name.
[alert-announce]
$ EXAMPLE_VAR=’hello world!’
[/alert-announce]
Note the single quotation marks used since the string content of our variable contains a space.
Also when special characters like ! are used in the string, apostrophes must be inserted instead of double quotes to enclose the the string.
! is special character in Bash as it is usually used to expand the shell history.
We can see the newly defined variable by using echo :
[alert-announce]
$ echo $EXAMPLE_VAR hello world!
[/alert-announce]
As said this is only a shell variable within the current Bash session and not an environmental variable.
This can be checked by using printenv :
[alert-announce]
$ printenv EXAMPLE_VAR hello world!
[/alert-announce]
No output is returned as the definition is not recognised as part of the environment.
Let’s take this as an opportunity to demonstrate a way of accessing the value of any shell or environmental variable.
Remember like in these example that to reference the value of a variable, precede it with a $ sign. This is so the shell knows to substitute the name of the variable for it’s content.
Environment Variables
To create one, export an existing shell variable into the shell’s persistent environment using the export command:
[alert-announce]
$ export EXAMPLE_VAR
[/alert-announce]
This time when we check the variable with printenv it will output.
[alert-announce]
$ printenv EXAMPLE_VAR hello world!
[/alert-announce]
The variable now descends into a sub shell child process and is retained from the parent, test this by starting anew shell session with bash :
[alert-announce]
$ bash $ echo $EXAMPLE_VAR hello world!
[/alert-announce]
To bypass having to set a variable and then export it to the environment, the process can be combined like this:
[alert-announce]
$ export INSTANT_ENV_VAR=”instant definition plus export!”
[/alert-announce]
Return to the parent shell we came from with exit , and try to echo the previously exported variable:
[alert-announce]
$ exit $ echo $INSTANT_ENV_VAR
[/alert-announce]
Notice no output is returned as environment variables can only be passed to child processes, and not the other way around. This is sensible for the most part as it “prevents programs from affecting the operating environment from which they were called”.
Also when you exit back into your main parent shell, the child shell environment is destroyed.
5 – Demoting and Unsetting Variables
To change an already set environment variable back into a lesser shell variable use the -n parameter with export :
[alert-announce]
$ export -n EXAMPLE_VAR
[/alert-announce]
Now nothing is returned when using printenv on the variable:
[alert-announce]
$ printenv EXAMPLE_VAR
[/alert-announce]
It’s still set as a shell variable so to undefine it completely from this local shell session you can use:
[alert-announce]
$ unset EXAMPLE_VAR
[/alert-announce]
6 – Persistent Variables
To create predefined variables at login depends upon how bash is started and which configuration file it uses to do so. The deciding factors on which file is used relies on the types of “login shell” that have being initiated by the user.
The types being either:
Login or Non-Login Interactive or Non-Interactive
So the two distinctions that are taken into account are whether the shell is being spawned as a “login” or “non-login” session. As well as whether the session is either an “interactive session” or “non-interactive” session.
Login
A login shell is a shell session that always begins by authenticating the user. If you are signing into a terminal session or through SSH and authenticate, your shell session will be classed and set as a “login” shell.
A session started as a login session will read configuration details from the /etc/profile file first, and then look for the first login shell configuration file it can find in the user’s home directory. In order to get user-specific configuration details.
These files are the first it can find out of ~/.bash_profile , ~/.bash_login , and ~/.profile .
Non-Login
If you start a new shell session from within your authenticated session, like earlier when we called the bash command from the terminal, a non-login shell session is started. This is as you were were not asked for any authentication details when you started the child shell.
A session defined as a non-login shell will always read /etc/bash.bashrc and then the user-specific ~/.bashrc file to help build its environment.
Interactive
An interactive shell session is a shell session that is attached to a terminal and in use. So a normal session that begins with SSH is usually defined as an interactive login shell. See “Non Interactive” in the next section to see the difference between the two.
Non-Interactive
A non-interactive shell session is one that is not attached to a terminal session, and not currently in use. For example a script run from the command line is usually run in a non-interactive, non-login shell.
Most notable non-interactive shells read the environment variable named BASH_ENV and read the file specified in this variable to construct the new shell environment.
Setting Environment Variables at Login
So there are a variety of circumstances that dictate which of the different files are needed to set predefined variables.
This has it’s advantages and gives a lot of flexibility for specific situations where you might want only certain settings for a login shell, and other different settings in a non-login shell.
Despite this to make things easier and more general, most people most of the time will want the same settings for both scenarios.
Depending upon your Linux distribution and personal setup, usually the login configuration files source the non-login configuration files. Meaning that you don’t have to define the variables in both files and can get away with defining environment variables that you want in both only inside the non-login configuration files. They will then be read in both scenarios as they’re sourced in the latter.
It’s also best to set them for your individual user and not system wide. so to make them available to both login and non-login shell sessions define these variables in the ~/.bashrc .
An example of the line to set a persistent environment variable in the .bashrc file would look like this:
[alert-announce]
.bashrc
$ export EXAMPLE_VAR=’hello world!’
[/alert-announce]
Which is the same as before whilst on the command line.
The next time you start a shell session, your environment variable declaration(s) are always read and passed on to the shell’s environment (including subsequent child shells too).
You can force your current session to read the config file at any time by typing in a terminal:
[alert-announce]
$ source ~/. bashrc
[/alert-announce]
To set them in the system wide files if you prefer, do the same except add the variable definition(s) to: /etc/profile , /etc/bash.bashrc , or /etc/environment instead.