Environment variables are super global variables.

What are environment variables?

You might already be aware of the concept of variable scopes.

What if you want a variable accessible from anywhere? What would be the top-most scope of any program? It would be your OS, yes.

Environment variables can be thought of as a global store of key-value pairs on the OS-level. A program (or many programs together) can read the values of these variables and alter their working.

Ever dealt with PATH issues? PATH is an environment variable as well.

What’s the need for ’em?

Imagine you have developed a simple program to print out the current temperature in the terminal. You have added color formatting for proper emphasis. But now you realise that not everyone is a fan of colors and need to provide a way to disable them. What do you do? And what if you maintain several small programs and need the setting for each one? You can create a commong config file and parse it or add CLI flags for each program. But it’s not quite elegant.

This is where the environment variables come in. Remember how these variables, once set, can be read by any program on your PC? What if there was a way the user could tell all the programs running on their machine that they hate colors? As the developer, if you adapt the NO_COLOR standard, you can just read-in the value of the NO_COLOR environment variable in all your programs. Thus giving users more power, and to you more flexibility.

Environment variables also come handy in keeping secrets. No longer do you need to artfully avoid committing the expensive API key. Set it as an environment variable, would you? ;)

Are environment variable names arbitrary?

For the most part, yes.

However over the years, certain variables have been adapted to mean something special through standards and specifications. Environment variables like LANG and PATH define how and what a computer runs.

Every shell and program comes with its own set of environment variables. Only thing is, you typically never touch them unless you are a heavy customizer or setting up an automated/headless system. The JAVA_HOME and the GOROOT variables required for advanced development setups are examples from out in the wild.

How do you set ’em and read ’em?

Setting environment variables is easy through CLI. Just open a shell, type in the variable name and the value you need assigned to it. But there are probably a hundred more ways to set/update these variables and what is best varies per case.

Setting environment variables

CLI is the most common way to alter these variables. Let’s see how:

On *—Nix shells

COOL_VAR=COOL_VAL # <name of the program here>
# OR
# and then run the program

On Windows

With PowerShell
# and then run the program
With CMD
:: and then run the program

Reading environment variables

Reading the values of these variables is just as easy as setting them.

On —Nix shells*

If you are reading the value of a particular variable, you can just echo it. However, echo doesn’t differentiate between environment and session variables.

echo $COOL_VAR

To list all the exported/environment variables, use this:

# or

On Windows

With CMD:

Just run the set command without any arguments.

With PowerShell:

To get the list of all set environment variables:

ls env:

Or to read a particular variable, echo it.

In Python:
import os
COOL_VAR = os.getenv("COOL_VAR")
In C
#include <stdlib.h>
const char* COOL_VAR = getenv("COOL_VAR");

Shell environments are ephemeral

Okay, so I lied in the beginning. There’s not just one super environment on your PC at the OS-level. Every terminal window/shell session has its own environment. And up until now we only changed this isolated environment.

If you close and reopen your shell at this point, all your changes will be lost. When editing the environment on-the-fly, the changes are limited to current shell process and its children. Once the shell process dies, its environment dies along with it.

So how to make environment changes persistent?

On *—Nix Systems

On most *—Nix systems, you can modify the *—rc file for your shell. *—rc files are automatically evaluated by shells in the init process. Just paste-in the commands that you ran in the terminal earlier, and changes will be (re)applied in every single window. You might notice however that GUI programs that you start independently do not see these changes. That could be because the variables aren’t imported into to the login session. The exact steps to do this correctly differ for every setup — depending on the display manager or the login shell used to the display server used. For example, while using GDM X11 session one should use .profile to make changes, but with GDM Wayland session oen should use environment.d files.

On Windows Systems

On Windows systems simply replacing set with setx in the command used earlier will make the changes permanent in and of itself.

However to do this graphically and in the recommended way, use the Windows Search to locate “Edit the system environment variables” option. You could also directly launch the window using the Run dialog (Win+R) and this command: rundll32 sysdm.cpl,EditEnvironmentVariables. From there it’s a matter of locating the right options and choosing and entering the right thing.

See this post on PATH where I mention the exact steps of modifying its value.

Happy Hacking ;)