# Linux Environment Variables: A Beginner’s Guide 

If you're working in a ***Linux environment***, there are chances that you have encountered ***environment variables -*** even if you didn't realize it at the time.

***Environment variables*** provides information that the ***shell*** and ***other programs*** use. They control things like the ***prompt*** and help the ***shell*** find ***programs*** when you type a ***command***. Whether you're an experienced ***system administrator*** or a new ***Linux user***, mastering ***environment variables*** is essential for customizing and controlling your ***shell*** experience.

### ***prompt***

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/1fd42507-5199-466b-9f7f-6986e7d09262.jpg align="center")

In this article, we will understand what ***environment variables*** are in ***Linux***. By the end of this article, you'll not only know how to ***view*** and s***et environment variables*** but also how to ***persist*** them.

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/7a269208-d70d-4162-8671-ffd6d149292d.jpg align="center")

### ***What are Environment variables***

***Environment variables*** are ***dynamic named values*** that programs use to ***get information*** and decide how they should ***work in Linux*** system.

***For example:***

```shell
HOME=/home/dev

#  HOME     --> name
# /home/dev --> value
```

***Linux*** represents ***environment variables*** as `name=value` pairs. When a ***program*** starts by ***shell***, ***program*** can ***recieve*** these ***values*** as a part of its ***environment***.

You can think ***environment variables*** as ***configuration settings*** that the ***shell*** and ***program*** understand how they should ***operate***.

***For example***:

*   The `PATH` variable ***tells*** the ***shell*** where to search for ***executable command when you type***.
    
*   The `HOME` variable ***stores*** the ***path*** of the ***home directory.***
    
*   The `LANG` variable defines ***system's language*** and ***character encoding***.
    

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/cc3319e2-c252-47ed-8a94-967adc230b7d.jpg align="center")

### ***What does the mean of shell*** `builtin`

A **shell built**\-in is a command built **right into your shell program** instead of being a **seprate external file** on your hard drive.

**Environment variables** themselves are not **shell built-ins** while **Built-ins** refer to the **commands**. Instead **environment variables are pieces of data**. It means **shell** is simply **stored text (a string) in your computer's memory**.

For example:

```shell
$SHELL
$HOME
$USER
```

```shell
USER=alex
HOME=/home/alex
PATH=/usr/bin:/bin
SHELL=Bash
```

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/026136de-1d90-49fb-ac25-cfde7c006dcf.jpg align="center")

### ***What does it mean of*** `executable`

An ***executables*** is just a file that ***contains program***. The words ***program*** and ***executable*** often used ***interchangably***. There are **two types** of program.

*   ***Compiled (binary) programs***
    
*   ***Interpreted programs***
    

**Compiled program :** A program that has been **converted** from **human readable code** to **machine (binary) code**.

**Machine code** is a set of instructions that a computer can **execute directly**. Because computer's **CPU** hardware is designed to execute **machine code**. Programming languages like `C`, `C++`, `JAVA` etc their code is **compiled** into **machine code** to run.

**Interpreted program** : A program that is **executed** by **another** **program**. The program that **executes** the **interpreted program** is called an ***interpreter***.

The ***interpreter*** reads the **interpreted program** and **executes** it. Programming languages like `python`, `JavaScript`, `Ruby` etc are typically **interpreted** as they run.

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/9762a232-6e46-4212-8509-efc73248d15f.jpg align="center")

Another example of **interperted** programs is `.sh` **shell scripts files**. Those are **interpreted** by **shell** program.

The `which` command tells the **location** of an ***installed*** **command line program**.

**For example** : `which sh` tells the location of **shell** program.

```shell
which sh
```

***Output:***

```shell
/usr/bin/sh
```

If you were `cat` `/usr/bin/sh`, you would not see the human readable code, that is because the **shell** is a c**ompiled program.**

### ***Run an*** `executable` ***in Linux***

You can run your **executable** file in **shell** by typing **file's path.**

```shell
mydir/program.sh
```

Interestingly, if the program is in the **current directory (mydir)**, you need to prefix `./` to run it.

```shell
./program.sh
```

As far as the file path go, `./program.sh` and `program.sh` are same. The dot `(.)` is an **alias** for the **current directory**.

We need to **prefix** it when run **executables** so that the `shell` knew that you're trying to **run a file** from a **file path** not an **installed command line programs** like `ls`, `mkdir`, `chmod` etc.

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/eb0a88bd-7332-42ef-8c5b-4f0f40441a71.jpg align="center")

### ***What is*** `shebang`

You can run an **executable program** by giving its **file path**, as long as you have **permission** to **execute** the **file**. You can run an **executable program** by giving its **file path**. But what about **scripts** that need an **interpreter**, such as `Bash` or `Python`, to run them?

The **system** needs to know which **program** should be used to **interpret** the file.

A `shebang` `(#!)` is a special line at the **top** of a **script** that tells the **system** which **program** should be used to **run** the **script**.

**The format of** `shebang` **is** :

```shell
#!interpreter [optional-arg]
```

For example, if your **script** is the `python` **script** and you want to use `python3` to **execute** the **script**, your **shebang** might look like this:

```shell
#!/usr/bin/python 3
```

This tells the **system** to use the `python 3` located at `/usr/bin/python 3` to **execute** the **script**.

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/66e7ffe0-2981-4431-8344-08494205378d.jpg align="center")

### ***Environment variables vs shell variables***

There is an important ***distinction (difference)*** between ***shell variables*** and ***environment variables:***

*   ***Shell variables*** are local to the ***shell session / current shell*** in which they are defined.
    
*   They does not put ***automatically*** into the ***Environment*** inherited by ***child processes***.
    

```shell
#Shell variable

name="dev"
echo $name
```

*   ***Environment variables*** are ***shell variables*** that has been `exported`, so that the ***program*** start by the ***shell*** can ***recieve them***.
    

```shell
#Environment variable

export name="dev"
echo $name
```

Now `name` is `exported`. If the ***Bash*** ***starts*** another ***program***, that ***program*** can ***recieve*** it.

```shell
             Bash
              |
       ┌──────┴──────┐
       │             │
   shell variable   exported / environment variable
       │             │
       │             ↓
       │        Child program
       │             │
       │             ↓
       │       can receive it
       │
       └── stays in Bash
```

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/566cb9ee-fa48-42d3-a5c2-641d5485fcd9.jpg align="center")

### *Types of Environment Variables in Linux*

1.  ***System-Wide Environment Variables***
    

These ***variables*** are ***availabe*** for ***all users*** of the ***system*** and are ***set*** by the ***system adminstrator***.

*   `/etc/environment`
    
*   `/etc/profile`
    
*   `/etc/bash.bashrc`
    

2\. ***User-specific Environment variables***

These ***variables*** are ***defined per user*** and ***stored*** in:

*   `~/.bashrc`
    
*   `~/.profile`
    
*   `~/.bash_profile`
    

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/cc088fe0-fb8e-48e9-b251-b0901542a164.jpg align="center")

### ***View Environment variable***

Before you can ***modify*** or ***use*** ***environment variables***, it's important to know how to ***inspect / view*** them.

1.  ***View all environment variables***
    

```shell
printenv
```

Both commands can ***show*** the ***environment variables*** of the ***current shell*** environment. `printenv` is specifically designed to ***print environment variable values***.

```shell
env
```

However, `env` command has a broader purpose. Its main job is to ***run a command with a modified environment***, although running `env` command ***without arguments displays the current environment variables***.

2.***View specific variable***

```shell
echo $HOME
    or
printenv HOME USER
```

***This command will display the current user's home directory.***

`printenv` also supports giving ***one or more*** ***variable names as arguments***.

3.***View all variables of shell***

```shell
set
```

***This command displays all shell variables and functions. It's broader than*** `printenv`.

When `set` is run without ***options*** or ***arguments***, it displays the ***name*** and ***value*** of ***shell variables and functions***.

### `PATH` ***Environment variable***

Sooner or later every developer installs a program, ***types*** its name in the `terminal` and gets hit with an `error : command not found`. Usually the culprit is `PATH` ***Environment variable***:

`PATH` stores **absolute directory paths** separated by `colons`. When you **run** a **command** without a **full path**, your **shell inspects each directory** in order and **executes** the **first matching file** with **execute permissions**.

It's the ***list of directories*** and it ***tells*** the `shell` ***search these directories*** when someone try to ***run*** a ***command.*** The directories are separated by `:`

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/08b1a82c-e56e-4dfb-913a-26a80c9c3ddf.jpg align="center")

***For example:***

```shell
echo $PATH
```

***Output look like this:***

```shell
/usr/local/bin:/usr/bin:/bin
```

It means the `shell` searches these directories when you type a command such as:

```shell
ls
```

***Shell searches like this:***

```shell
ls
 ↓
/usr/local/bin
 ↓
/usr/bin
 ↓
/bin
```

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/40eb9e4c-b7f1-4ada-8790-f6844f7b51f6.jpg align="center")

> If the **same executable name** exists **in more than one directory**, the **first directory** in this list wins.

### ***Setting and Exporting Environment Variables***

***You can define variables in the shell but these aren't permanent***

### ***1.Setting a variable***

**To create a variable:**

```shell
MY_VAR="hello"
```

This creates a ***shell variable*** named `MY_VAR` and gives it the value `"hello"`

**To check the variable:**

```shell
echo $MY_VAR
    or
printenv MY_VAR
```

***This is basic*** `Bash` ***syntax for assigning and checking the variable.***

### ***2.Create Environment Variable***

A normal ***shell variable*** is available to the ***current shell***. If you want programs ***started*** by the ***shell*** to ***recieve*** the ***variable***, you can ***export*** it.

`Bash's` ***export*** command marks a variable to ***be passed*** to ***subsequently (after)*** ***executed*** command.

**To create the variable:**

```shell
export MY_VAR="hello"
```

**To check the variable:**

```shell
echo $MY_VAR
```

### ***3.Using a variable***

Once a ***variable*** has a ***value***, you can use `$` followed by ***its name***:

```shell
echo "Variable is saying: $MY_VAR"
```

***Output:***

```shell
Variable is saying: hello
```

### ***4.Temporary*** `PATH` ***update***

You can temporarily add a directory to the `PATH` ***environment variable***

```shell
export PATH="$PATH:/opt/myapp/bin"
```

This ***adds*** `/opt/myapp/bin` to the ***end*** of the existing ***PATH.***

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/e7ca2255-229a-46ff-a575-4cc78a8b9e9a.jpg align="center")

### ***Making Environment Variables persistent***

***Variables*** defined in the ***shell*** are ***lost*** ***once the session ends***. You need to ***store*** them in a ***shell configuration file***.

### ***common shell startup files:***

### `~/.bashrc`

*   `~/.bashrc` : This files is normally read when `Bash` starts as an i***nteractive non-login shell***.
    
*   ***For example,*** when you open a ***new terminal window***, your ***terminal*** will often ***start*** an ***interactive Bash shell***, which commonly reads - `.bashrc` . This makes `.bashrc` a common place for things such as:
    

```shell
export PATH="$HOME/.local/bin:$PATH"
export EDITOR=vim
```

### `~/.bash_profile`

*   `~/.bash_profile` : This ***file*** can be ***read*** when `Bash` starts as a ***login shell***. `Bash` ***checks these files in this order***:
    

```shell
~/.bash_profile
~/.bash_login
~/.profile
```

*   `Shell` uses the ***first one*** that ***exists*** and ***readable***.
    

A common setup is for `.bash_profile` to load `.bashrc`, so that the same ***interactive*** ***configuration*** is availabe in ***both situations***.

```shell
if [ -f ~/.bashrc ]; then #if .bashrc is availabe, source that. 
    . ~/.bashrc
fi
```

### `~/.profile`

*   `~/.profile` : This another ***login start up file***. `Bash` checks it after `~/.bash_profile`, `~/.bash_login`.
    

```shell
.bash_profile = .bash_login = .profile ❌️
```

They are ***alternative login startup files***, and `Bash` doesn't a***utomatically read all three***.

### `~/.zshrc`

If you use `ZSH` instead of `Bash`, `ZSH` has its own ***startup files***.

`~/.zshrc` is read for ***interactive ZSH shells.***

***So:***

```shell
Bash → ~/.bashrc
Zsh  → ~/.zshrc
```

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/cbc1cdee-220e-4853-8f89-cf62c8328ba9.jpg align="center")

### ***Adding Environment Variables to*** `.bashrc`

Suppose you want these settings whenever your ***interactive Bash shell starts***:

```shell
export EDITOR=vim
export PATH="$HOME/.local/bin:$PATH"
```

You can add them to: `.bashrc` file. Then when `Bash` reads `.bashrc`, it ***executes*** those ***commands*** and sets the ***variables***.

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/ced0b73e-bc72-4832-92c0-6ac1a4bf85ca.png align="center")

### ***Apply changes without restarting the terminal***

After editing `.bashrc` , the changes ***are not automatically applies*** to your ***already running shell***. You can ***read*** the file ***manually*** with:

```shell
source ~/.bashrc
```

`source` tells `Bash` to ***read*** and ***execute*** the commands in that ***file*** in the ***current shell***.

You can also use:

```shell
. ~/.bashrc
```

The `.` is another form of `source` ***command*** in `Bash`.

![](https://cdn.hashnode.com/uploads/covers/695114b01f48b622b5631972/bab19b71-a394-42bb-8971-0cf4f55b9821.jpg align="center")

### ***Conclusion***

***Environment Variables*** are a fundamental part of the ***Linux shell***. They provide essential configuration for your system and applications.
