Each Linux process has its own set of environment variables, which it inherits from its parent. For example, when we execute a command in our shell, the command inherits the environment variables of the shell.
Although we’ll be using Bash, all examples in this article should also work in other POSIX-compatible shells.
2. Global Environment Variables
When we start a shell, we create our shell with a set of predefined environment variables. We can declare them globally or on a per-user basis.
With Bash, we declare global variables in /etc/profile. But, we recommend declaring them in their own script files and putting those in /etc/profile.d. Bash will automatically pick these up.
Global variables affect all users in the system. Each user can create a set of “global” environment variables for their own by creating ~/.profile in their home directory.
One of the most common environment variables we use on a daily basis is the PATH variable. PATH contains a list of locations for our shell to search for executables. We can add something to our PATH by creating a ~/.profile containing similar information:
Here, we actually redeclare the PATH variable and set its value to the current value of PATH and add /path/to/executable/ to it.
In the next sections, we’ll describe the commands most commonly used to manage environment variables. Let’s start env and printenv.
3. env and printenv
We’ve already mentioned that each process runs in its own environment. We can use env to run a program in a modified environment, by supplying additional environment variables:
env CUSTOM_VAR=42 /path/to/script.sh
In this example, env will execute /path/to/script.sh in an environment that is a copy of our shell environment with CUSTOM_VAR as an added environment variable with value 42.
Actually, env accepts a list of space-separated variables. Therefore, we can add multiple variables:
env VAR_ONE=1 VAR_TWO=2 /path/to/script.sh
We can also unset or remove variables by preceding them with -u:
env -u PATH /path/to/script.sh
This will run our script in a copy of the current environment, but without the PATH variable.
We can even run our script in an empty environment:
env -i /path/to/scripts.sh
Finally, running env without arguments will print a list of all variables in the current environment. We can accomplish the same with printenv:
[vagrant@localhost ~]$ set HOSTNAME=localhost.localdomain TERM=xterm-256color SHELL=/bin/bash HISTSIZE=1000SSH_TTY=/dev/pts/0 USER=vagrant MAIL=/var/spool/mail/vagrant PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin PWD=/home/vagrant LANG=en_US.UTF-8 HOME=/home/vagrant LOGNAME=vagrant
We can also print values of particular variables by providing a space-separated list of variable names:
printenv HOSTNAME PATH HOME
This will print:
localhost.localdomain /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin /home/vagrant
We should not confuse environment variables with shell variables. Shell variables are variables that apply to our current shell only and are not inherited by any programs or scripts that we execute.
We can get an overview of all variables that apply to our current shell by calling set:
[vagrant@localhost ~]$ set BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=() HOSTNAME=localhost.localdomain TERM=xterm-256color SHELL=/bin/bash HISTSIZE=1000SSH_TTY=/dev/pts/0 USER=vagrant MAIL=/var/spool/mail/vagrant PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin PWD=/home/vagrant LANG=en_US.UTF-8 HOME=/home/vagrant LOGNAME=vagrant
We can see shell variables specific to Bash and all environment variables we printed before using printenv.
Shell variables aren’t inherited by subprocesses, but we can export them to make them visible. We can best explain this by an example.
First, let’s create a new shell variable:
We can print the value of our variable with echo:
echo "Custom var value: $CUSTOM_VAR" 42
To verify that the variable can’t be seen from a subprocess, let’s put the echo command in a script that we’ll name print_custom_var.sh:
#!/bin/bash echo "Custom var value: $CUSTOM_VAR"
When we run the script the output will be:
./print_custom_var.sh Custom var value:
Our script can’t see the value of CUSTOM_VAR, because the CUSTOM_VAR doesn’t exist for the script. We can make it visible to subprocesses with export:
Now, let’s run the script again:
./print_custom_var.sh Custom var value: 42
In this article, we learned how we can manage environment variables.
First, we learned how to set global environment variables using locations like /etc/profile.d and ~/.profile. Then, we saw how to manage environment variables using env, printenv, and export.