107

I have been scouring the internet, and cannot seem to find a solution to permanently adding an environment variable, specifically when my OS is macOS Mojave (10.14). It seems there are a lot of tutorials for past versions of the OS, but none for this one one. It also seems every old method has become outdated.

I want to add an environment variable ENV_VAR=12345 to my Mac, so that I can import it into a Python module using os.environ['ENV_VAR']

The most relevant tutorial I have found is this, but it doesn't quite do the trick for me. A lot of others tell you how to temporarily add environment variables to bash, but I don't think this is good enough. I want the addition to be there if you restart terminal.

Can you please either provide a short tutorial or point me to the correct/modern tutorial?

UPDATE: I should have mentioned that I use zsh. This was key.

4
  • Look at unix.stackexchange.com/questions/346336/… and/or unix.stackexchange.com/questions/48870/global-bash-profile to persist environment variables.
    – tk421
    Commented Apr 9, 2019 at 22:18
  • Is the python script run from the command line or us an app run from desktop or finder?
    – mmmmmm
    Commented Apr 10, 2019 at 8:13
  • @Mark the script is run from the command line! Via python -m module_name Commented Apr 10, 2019 at 15:20
  • I'm voting to close this question as off-topic because the question is unclear as the shell is zsh which is not mentioned. The tutorials etc are for a different case. If the question was I use zsh and how do I set a environment variable for python then OK The question and answers will just confus anyone new reading them
    – mmmmmm
    Commented Apr 10, 2019 at 17:09

7 Answers 7

119

Bash

Since Bash is typically the default shell you can open up this file in your home directory:

$ vim ~/.bash_profile

And add your variable to this file:

export ENV_VAR=12345

You can do this without even having to edit this file if you like, using the following one-liner:

$ echo 'export ENV_VAR=12345' >> ~/.bash_profile

And then confirm like so:

$ cat ~/.bash_profile
for i in ~/.bash_profile.d/[0-9]*; do
  . "$i"
done
export ENV_VAR=12345

After doing the above, if you open a new terminal you should see that environment variable has been set:

$ echo $ENV_VAR
12345

Zsh

If you find that you're using an alternative shell such as zsh, that uses a different set of configuration files maintained within your home directory, ~. Luckily the syntax of the changes is basically the same, just different files. So you can add the above example to this file instead:

$ echo 'export ENV_VAR=12345' >> ~/.zshenv

And then when you launch a zsh:

$ echo $ENV_VAR
12345

References

2
  • Note: If you want an ENV to be accessible outside of something launched from a shell context, like when running a Python script directly, setting it in your bash/zsh config files won't solve it. You'd need to use launchctl setenv ENV_NAME ENV_VALUE to make it available everywhere. See my other answer for more info.
    – Chris
    Commented Dec 20, 2021 at 3:32
  • 3
    In MacOS Monterey, I don't have zshenv under user's dir nor under /etc. Thus I'm using $ echo 'export ENV_VAR=12345' >> ~/.zshrc to inject this environment variable.
    – Zhou Haibo
    Commented Dec 28, 2021 at 5:41
47

First, execute in a terminal with zsh (Z Shell):

echo 'export ENV_VAR=12345' >> ~/.zshenv

Then, reload changes:

source ~/.zshenv

Finally, test if your new variable is set:

echo $ENV_VAR

Note: By standard, the .zshenv file should only contain environment variables setting commands. .zshenv is sourced on all invocations of the shell, hence it will persist even after you restart your machine.

1
  • 1
    Maybe a bit obvious for experts but the source command did the trick for me and I didn't even have to reopen another terminal. (as opposed to the accepted answer)
    – Jelle
    Commented Jan 14, 2022 at 12:46
4

The other solutions describe how to set an environment variable in all your zsh/bash shell instances. But they don't set a permanent ENV that's available everywhere on in macOS, including in every launched program.

For example, if you define ENV_VAR=1 your .zshrc but you launch Python directly without launching it from a shell, then anything set in your .zshrc wouldn't be available in os.environ['...'].

To solve this, you can set a truly global environment variable on macOS at the system wide level using launchctl like this:

launchctl setenv "ENV_VAR" "12345"

After running that, every newly launched program will see the ENV_VAR environmental variable, including shell instances as well as things launched without a shell. You will need to close your terminal app and re-open for it to be in your shell. It also won't show up in ssh sessions, which aren't launched by launchd like GUI programs.

Update: It seems that this does not persist across system restarts. You can find some discussion for that here. Funnily, a decent solution to this is just to put launchctl setenv ... in your shell's .zshenv or .bash_profile. Though that means you'll need a launch a shell before the global vars are set, so you can see some more robust solutions that involve creating a new launchd job here.

2

For what it's worth, I use this portable shell function to quickly set & permanently add environment variables.

I predominantly use zsh, but it can be easily adapted for bash or other POSIX-compliant shells.

# -----------------------------------------
#  Create permanent environment variable
#
#  $1 - variable name
#  $2 - variable definition
#  @requires: '~/.zshrc' or '~/.bashrc'
# -----------------------------------------
function new_env_var {
  local detected_shell="$(ps -o comm= -p $$)"
  local rcfile=$(echo "${HOME}/.${detected_shell//-/}rc")
  if [[ -f $rcfile ]]; then
    local var_name; local var_val
    if [ -z "$1" ]; then
      echo "variable name (e.g. 'NEW_VAR' for '\$NEW_VAR'):"; read var_name
    else
      var_name=$1
    fi
    if [ -z "$2" ]; then
      echo "variable definition:"; read var_val
    else
      local s2 var_val="${@//${var_name}/}"
      until s2="${var_val#[   ]}"; [ "$s2" = "$var_val" ]; do var_val="$s2"; done
    fi
    echo "export $var_name=\"$var_val\"" >> $rcfile; export $var_name="$var_val"
  else
    echo "No $detected_shell runcom file found. Please make sure $rcfile exists."
  fi
}

You can use it like so:     new_env_var MY_ENV_VAR 9,999

2

shows all hidden files like .bash_profile and .zshrc $ ls -a

Starting with macOS Catalina, macOS uses zsh instead of bash for newly created accounts.

Check which shell running:

$ echo $SHELL
/usr/zsh
$ cd $HOME
$ open -e .zshrc

or if using vim

$ vi .zshrc

Then add it like this

$ export my_var="/path/where/it/exists"
$ export PATH=$PATH:/$my_var/bin

For example: if installed app named: myapp in /Applications Then

export MYAPP_HOME=/Applications/myapp
export PATH=$PATH:$MYAPP_HOME/bin

or shortcut

export PATH=${PATH}:/Applications/myapp/bin
0

The file names used to set environment variables differ depending on which shell you use. By default, the mac assigns the bash shell to new users. echo $SHELL if unsure.

From here, check the man page. e.g.: man bash and it will document the files it will execute at runtime. You can add an environment variable to one of those files.

For bash, make sure you export the variable or it wont be inherited by a child process. e.g.: export ENV_VAR=12345 or ENV_VAR=12345; export ENV_VAR

-1

UPDATE: read the comments to @slm's answer. I should have been editing ~/.zshrc not ~/.bash_profile, because I use zsh. The more you know! The below answer also seemed to work, but hacky.


Thanks to @Tim Campbell and @slm, I was able to get something working.

Background

echo $0 outputs -zsh

echo $SHELL outputs /bin/zsh

echo $PATH outputs /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin


My "Hacky" Solution

I made a shell script configure_env.sh and put in in ~/Documents

#!/bin/zsh
export ENV_VAR=12345

I then ran chmod +x ~/Documents/configure_env.sh

I then did nano ~/.bash_profile and appended source ~/Documents/configure_env.sh

Then, when I typed echo $ENV_VAR, it returned 12345

:) thank you again to Stack Overflow!

1
  • 3
    Ugh this is a mess and a dredful idea- you need to edit one file only and add export ENV_VAR=12345 to it and the file is .zshrc So delete everything after I use zsh. ALso the fact you are using zsh must be in the question
    – mmmmmm
    Commented Apr 10, 2019 at 17:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .