931

What is the proper way to modify environment variables like PATH in OS X?

I've looked on Google a little bit and found three different files to edit:

  • /etc/paths
  • ~/.profile
  • ~/.tcshrc

I don't even have some of these files, and I'm pretty sure that .tcshrc is wrong, since OS X uses bash now. Where are these variables, especially PATH, defined?

I'm running OS X v10.5 (Leopard).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul Wicks
  • 62,960
  • 55
  • 119
  • 146
  • `env "switch.1.disabled=true" open -n /Applications/Eclipse.app/` to launch GUI application with a new set system environment. – Hong Aug 09 '16 at 01:08
  • See also: https://stackoverflow.com/questions/25385934/setting-environment-variables-via-launchd-conf-no-longer-works-in-os-x-yosemite – ThomasR Aug 06 '17 at 08:30
  • `.tcshrc` is obviously only useful if you use Tcsh. If you do, welcome to the 21st century! You'll be surprised to hear that there are now Bourne-compatible free open-source shells. – tripleee Jun 09 '22 at 09:16
  • related on Ask Different (Stack Exchange's Apple site): [How do I set environment variables on OS X?](https://apple.stackexchange.com/q/106778/479746) – starball May 06 '23 at 22:53

33 Answers33

689

Bruno is right on track. I've done extensive research and if you want to set variables that are available in all GUI applications, your only option is /etc/launchd.conf.

Please note that environment.plist does not work for applications launched via Spotlight. This is documented by Steve Sexton here.

  1. Open a terminal prompt

  2. Type sudo vi /etc/launchd.conf (note: this file might not yet exist)

  3. Put contents like the following into the file

    # Set environment variables here so they are available globally to all apps
    # (and Terminal), including those launched via Spotlight.
    #
    # After editing this file run the following command from the terminal to update
    # environment variables globally without needing to reboot.
    # NOTE: You will still need to restart the relevant application (including
    # Terminal) to pick up the changes!
    # grep -E "^setenv" /etc/launchd.conf | xargs -t -L 1 launchctl
    #
    # See http://www.digitaledgesw.com/node/31
    # and http://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x/
    #
    # Note that you must hardcode the paths below, don't use environment variables.
    # You also need to surround multiple values in quotes, see MAVEN_OPTS example below.
    #
    setenv JAVA_VERSION 1.6
    setenv JAVA_HOME /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
    setenv GROOVY_HOME /Applications/Dev/groovy
    setenv GRAILS_HOME /Applications/Dev/grails
    setenv NEXUS_HOME /Applications/Dev/nexus/nexus-webapp
    setenv JRUBY_HOME /Applications/Dev/jruby
    
    setenv ANT_HOME /Applications/Dev/apache-ant
    setenv ANT_OPTS -Xmx512M
    
    setenv MAVEN_OPTS "-Xmx1024M -XX:MaxPermSize=512m"
    setenv M2_HOME /Applications/Dev/apache-maven
    
    setenv JMETER_HOME /Applications/Dev/jakarta-jmeter
    
  4. Save your changes in vi and reboot your Mac. Or use the grep/xargs command which is shown in the code comment above.

  5. Prove that your variables are working by opening a Terminal window and typing export and you should see your new variables. These will also be available in IntelliJ IDEA and other GUI applications you launch via Spotlight.

Frankenmint
  • 1,570
  • 3
  • 18
  • 33
Matthew McCullough
  • 17,160
  • 7
  • 39
  • 38
  • So you're saying the right answer is wrong? I have no had any success with environment.plist. – Dan Rosenstark Jan 18 '10 at 22:39
  • 4
    I'm saying that the accepted answer (environment.plist) has not been successful for me. I've successfully used the launchd.conf approach on 10.5 and 10.6 on four machines. – Matthew McCullough Jan 19 '10 at 23:53
  • 62
    Is there any way of doing this **without** doing a **system reboot**? – sorin Feb 05 '10 at 14:18
  • Not that I'm aware of. I don't know of any "reload" type of command that causes this to be re-read. A reboot seems to always be necessary. – Matthew McCullough Feb 05 '10 at 17:41
  • 1
    I also had to use /etc/launchd.conf and reboot for it to take affect. – David Collie May 02 '10 at 14:08
  • 40
    The limitation mentioned above applies to MacOS X 10.5. However MacOS X 10.6 does not have this limitation anymore and setting the values inside environment.plist works fine even for apps launched via spotlight. So the selected answer is correct for Snow Leopard ;-) – Louis Jacomet Jun 09 '10 at 14:54
  • 5
    Setting `launchd.conf` is one way, but needs a reboot (to restart launchd). If you want to avoid a reboot, see my answer http://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x/3756686#3756686 – Matt Curtis Sep 21 '10 at 01:25
  • 3
    By the way, the method of launchd.conf / setenv won't work if your 'value' contains spaces (setenv MY_VAR something with a space *or* setenv MY_VAR 'something with a space that still wont work'). – Andrew Wyatt Sep 20 '11 at 15:33
  • 1
    I have MacOS 10.6 and want to do this on a **per user** basis just for my user. That is so when I run Xcode it is inherited by the makefiles it runs during the build. I just tried creating a ~/.MacOS/environment.plist file and after rebooting the new variable is not present either in the terminal bash shell, or inherited by Xcode. Also in a .plist file how does one append or prepend an item onto the path ( that is access the prior value of the variable to create the new one ) ????? – peterk Oct 09 '11 at 22:37
  • 2
    Oh well ... from MacOSX 10.6.6 man page: $HOME/.launchd.conf Your launchd configuration file (currently unsupported). – peterk Oct 10 '11 at 00:15
  • If you are uncomfortable with VI (like me) This is a lifesaver: http://www.lagmonster.org/docs/vi.html – Simon Tower Nov 30 '11 at 01:14
  • 26
    There are several problems with the presented launchd approach. Most are specific to the PATH environment variable, but the asker did mention PATH specifically. 1) items in launchd.conf do not get applied in interactive shells such as ssh into the system. 2) having the line "setenv PATH /testdir" appends to the PATH in Terminal.app, but blows away all other PATH items in OS X Applications' Environments. 3)Doing "setenv PATH ${PATH}:/testdir" in /etc/launchd.conf doesn't properly expand existing $PATH 4)launchd.conf applies to all users, instead of just one. Not that I have any better soln. – NoahR Dec 09 '11 at 01:43
  • Hi Mathews your answer really helps.. Is is possible to update your answer to how to save the file in mac because i am very new to MAc – vinothp Oct 01 '12 at 11:05
  • 1
    Hi, based on this I created a Java Tool to set the JAVA_HOME environment by mouse click: http://www.guigarage.com/2013/02/datafx-observableexecutor-preview/ – Hendrik Ebbers Feb 09 '13 at 11:23
  • 3
    @NoahR - the method described at the following link worked well for the PATH environment variable for me when launching from the terminal (did not try it any other way - OSX version 10.7): http://serverfault.com/questions/16355/how-to-set-global-path-on-os-x – Mick Mar 19 '13 at 13:53
  • @NoahR It is not *interactive* shells in general - works fine with local shells in `Terminal.app`, `ssh` is the problem - possibly, because it doesn't use Launch Services on the remote machine. To work around that problem, execute the following once connected: `eval "$(launchctl export)"` - see also: http://apple.stackexchange.com/questions/87282/in-mountain-lion-how-do-i-set-the-path-environment-variable-unified-for-all-newl – mklement0 May 31 '13 at 21:26
  • As for the `grep` command in the answer for making pending changes take effect even before a reboot: turns out that (at least as of OS X 10.8.3) `launchctl` can read commands from `stdin` - except that it can't deal with comment lines! Thus, the (relatively) easiest and most robust way to load pending changes is as follows: `egrep -v '^\s*#' "/etc/launchd.conf" | launchctl`. – mklement0 Jun 01 '13 at 03:18
  • 2
    To make this work for applications started from the Dock I had to restart it using **sudo killall Dock** and then restart my app. – Perry Oct 23 '13 at 19:27
  • Does this need to be modified at all for Mavericks? – Tango Oct 30 '13 at 03:35
  • 2
    "setenv PATH x" does not work in Mavericks. See http://apple.stackexchange.com/questions/106355/setting-the-system-wide-path-environment-variable-in-mavericks – Maxence Nov 18 '13 at 16:07
  • @Pierre-LucPaour here is the right one: http://www.guigarage.com/2013/02/change-java-version-on-mac-os/ – Hendrik Ebbers Oct 14 '14 at 10:26
  • For Yosemite Users: http://stackoverflow.com/questions/36141784/sonarqube-local-script-in-intellij-cant-find-mvn-ioexception-no-such-directory – Chris Manning Mar 24 '16 at 19:12
  • 2
    This no longer works (at least for 11.6 Big Sur). `man launchctl`: "_The /etc/launchd.conf file is no longer consulted for subcommands to run during early boot time; this functionality was removed for security considerations._" – kgadek Dec 02 '21 at 16:38
  • Don't ever assume anyone knows how to use `vi`. That's completely irrelevant to editing a text file. You could just say "create a text file, and enter these contents...". Much better, you could just assume macOS' `open` works and write `sudo touch /etc/launchd.conf && sudo open /etc/launchd.conf` – iono Jun 15 '22 at 12:51
  • Just updated to MacOS 13.1 (Ventura) and `/etc/launchd.conf` no longer works. I can set environment variables later using `launchctl` though... – Hubro Feb 02 '23 at 13:38
310

Don't expect ~/.launchd.conf to work

The man page for launchctl says that it never worked:

DEPRECATED AND REMOVED FUNCTIONALITY

launchctl no longer has an interactive mode, nor does it accept commands from stdin. The /etc/launchd.conf file is no longer consulted for subcommands to run during early boot time; this functionality was removed for security considerations. While it was documented that $HOME/.launchd.conf would be consulted prior to setting up a user's session, this functionality was never implemented.

How to set the environment for new processes started by Spotlight (without needing to reboot)

You can set the environment used by launchd (and, by extension, anything started from Spotlight) with launchctl setenv. For example to set the path:

launchctl setenv PATH /opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

Or if you want to set up your path in .bashrc or similar, then have it mirrored in launchd:

PATH=/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin
launchctl setenv PATH $PATH

There's no need to reboot though you will need to restart an app if you want it to pick up the changed environment.

This includes any shells already running under Terminal.app, although if you're there you can set the environment more directly, e.g. with export PATH=/opt/local/bin:/opt/local/sbin:$PATH for bash or zsh.

How to keeping changes after a reboot

New method (since 10.10 Yosemite)

Use launchctl config user path /bin:/usr/bin:/mystuff. See man launchctl for more information.

Previous method

The launchctl man page quote at the top of this answer says the feature described here (reading /etc/launchd.conf at boot) was removed for security reasons, so ymmv.

To keep changes after a reboot you can set the environment variables from /etc/launchd.conf, like so:

setenv PATH /opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

launchd.conf is executed automatically when you reboot.

If you want these changes to take effect now, you should use this command to reprocess launchd.conf (thanks @mklement for the tip!)

egrep -v '^\s*#' /etc/launchd.conf | launchctl

You can find out more about launchctl and how it loads launchd.conf with the command man launchctl.

Matt Curtis
  • 23,168
  • 8
  • 60
  • 63
  • 2
    Very nice one! The advantage of using environment.plist though seems to be that OS X honours the contents of that files without the hassle of having to fire up a terminal first. Anyway, I think your answer mainly concentrated on avoiding the necessity of a reboot, so thx for that. – fotNelton Sep 27 '10 at 08:51
  • 2
    @kapuzineralex Yes it avoids a reboot, also it changes the environment for programs started from Spotlight, which `environment.plist` does not do. – Matt Curtis Sep 29 '10 at 03:22
  • 2
    Setting environment on this way did work for me only till I rebooted. The environment variable did not last after I rebooted the mac. Matthew's answer worked perfectly for me. – Shamal Karunarathne Aug 19 '11 at 04:08
  • 8
    @Shamal: I +1'd your comment but bear in mind Matthew's answer *requires* a reboot, whereas I am pointing out the correct way to change it without a reboot. If you want both, I suggest you put your path settings in launchd.conf (so they persist across reboots), and then use a script with something like this "source /etc/launchctl.conf ; launchctl setenv PATH $PATH", so you can also "refresh" when you don't want to reboot. – Matt Curtis Aug 22 '11 at 05:00
  • 2
    this works fine, but must be executed each time after the machine is booted. And if one set 'PATH' this does not take this appears to be a special case. - is there a way to have this automatic **per user** ?? and is there a way to do this with **PATH** such that it will be inherited by XCode and tus the makefiles and scripts it invokes ?? – peterk Oct 09 '11 at 23:10
  • @peterk To have it "automatic per user" you could add it to your /etc/profile or similar - check your users' shell manpages for info on what startup scripts they read. It should then be a simple matter of software engineering to refactor the launchd.conf, /etc/profile and others to share the same configuration. If you launch XCode (or anything else) via spotlight, the ONLY way to set up a path for it before you launch it is to set launchd - either with launchd.conf or launchctl. If you're running make from a shell, you just need to ensure your shell exports PATH. – Matt Curtis Oct 11 '11 at 01:24
  • All: if you're looking for a way of combining solutions, see @pajato0's answer http://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x/5444960#5444960 – Matt Curtis Oct 11 '11 at 01:31
  • 5
    @MattCurtis Could you please edit your answer **directly** to make it clear that while there is no reboot required, the changes will actually be **lost** after a reboot? Also, the correct way to apply changes in `etc/launchd.conf` before a reboot would be to use the approach in @MatthewMcCullough's answer: `egrep "^setenv\ " /etc/launchd.conf | xargs -t -L 1 launchctl`. – mklement0 May 31 '13 at 21:19
  • 1
    @mklement I've made that change, thanks for the suggestion. People finding this question have different goals: some people want to set the environment for something they're about to launch, others want to make a permanent change, others are just dealing with the shell. – Matt Curtis May 31 '13 at 23:31
  • 2
    @MattCurtis Thanks, I appreciate the update - and thanks for reading the manual :) I was getting excited about a *user*-level option via `~/.launchd.conf`, but it turns out it **doesn't work as of OS X 10.8.3** (I've tried several variations) - the file is simply ignored; I've filed a bug with Apple. Also, it turns out that `launchctl` (as of at least OS X 10.8.3) can read commands from `stdin` - except that it can't deal with comment lines!. Thus, the (relatively) best way to load pending changes is as follows: `egrep -v '^\s*#' "/etc/launchd.conf" | launchctl`. – mklement0 Jun 01 '13 at 04:16
  • @mklement Good pickup. And good advice with reloading config, I'll add it to the answer! – Matt Curtis Jun 01 '13 at 10:27
  • 1
    @Martin "Restart the dock"? A more general thing to say is, processes already started can not have their environments modified in this way. – Matt Curtis May 18 '14 at 07:37
  • Does the `launchctl config ` method still work in Ventura? I can't get Android Studio / Gradle to recognize paths that I add to PATH with this method. *Update:* It actually works until I reboot the system. Is there a way to persist the changes? – szx Nov 30 '22 at 19:54
109

Up to and including OS X v10.7 (Lion) you can set them in:

~/.MacOSX/environment.plist

See:

For PATH in the Terminal, you should be able to set in .bash_profile or .profile (you'll probably have to create it though)

For OS X v10.8 (Mountain Lion) and beyond you need to use launchd and launchctl.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • 4
    This is only if you actually expect them to be used by graphical apps. Since these don't typically use environment variables, it's not a very good place to set them. – Chris Hanson Sep 25 '08 at 21:33
  • 21
    There's some very good examples of graphical apps that use environment variables. IntelliJ for example, likes to be able to see M2_HOME to know where Maven lives. To get it to see the variable, you'll need to set it in /etc/launchd.conf instead of environment.plist. – Matthew McCullough Feb 26 '09 at 03:58
  • 3
    For reference: using `preferences.plist` was less than ideal with OS X 10.5 since at that time `preferences.plist` was not read for applications launched through spotlight, see comment by Louis to Matthew's answer and http://email.esm.psu.edu/pipermail/macosx-emacs/2010-May/002113.html . For OS X 10.6 `environment.plist` works just like it should. – Janus Sep 14 '10 at 01:36
  • The behavior with environment.plist appears to be a rolling target. In OS X 10.6.8, if PATH is set in environment.plist, then when .app applications are launched, they see only that path, and not the standard system path (/usr/bin:/bin:etc.) This behavior bugs up a lot of things, one easy one to see is launching the X11.app in Applications/Utilities. I have been bitten by PATH in environment.plist several times now. I'm done with it. – NoahR Dec 09 '11 at 00:09
  • 17
    This is no longer applicable to OSX 10.8 http://apple.stackexchange.com/questions/57385/where-are-system-environment-variables-set-in-mountain-lion – thatsmydoing Aug 23 '12 at 04:24
  • 2
    @tim_yates Could you please edit the first line of your answer to read "Up to *and including* **Lion** (10.*7*)", given that that is what's correct? I tried to make that edit to the original, ambiguous "Up to Mountain Lion", and the reviewers botched it. – mklement0 Jun 01 '13 at 02:52
  • to complement tim answer, here is the ultimate resource about this http://www.dowdandassociates.com/blog/content/howto-set-an-environment-variable-in-mac-os-x/ – João Pinho Feb 20 '14 at 23:45
  • @KorayTugay Added a different link – tim_yates Oct 01 '14 at 10:27
79

Solution for both command line and GUI applications from a single source (works with Mac OS X v10.10 (Yosemite) and Mac OS X v10.11 (El Capitan))

Let's assume you have environment variable definitions in your ~/.bash_profile like in the following snippet:

export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)"
export GOPATH="$HOME/go"
export PATH="$PATH:/usr/local/opt/go/libexec/bin:$GOPATH/bin"
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
export MANPATH="/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"

We need a Launch Agent which will run on each login and anytime on demand which is going to load these variables to the user session. We'll also need a shell script to parse these definitions and build necessary commands to be executed by the agent.

Create a file with plist suffix (e.g. named osx-env-sync.plist) in ~/Library/LaunchAgents/ directory with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>osx-env-sync</string>
  <key>ProgramArguments</key>
  <array>
    <string>bash</string>
    <string>-l</string>
    <string>-c</string>
    <string>
      $HOME/.osx-env-sync.sh
    </string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

-l parameter is critical here; it's necessary for executing the shell script with a login shell so that ~/.bash_profile is sourced in the first place before this script is executed.

Now, the shell script. Create it at ~/.osx-env-sync.sh with the following contents:

grep export $HOME/.bash_profile | while IFS=' =' read ignoreexport envvar ignorevalue; do
  launchctl setenv "${envvar}" "${!envvar}"
done

Make sure the shell script is executable:

chmod +x ~/.osx-env-sync.sh

Now, load the launch agent for current session:

launchctl load ~/Library/LaunchAgents/osx-env-sync.plist

(Re)Launch a GUI application and verify that it can read the environment variables.

The setup is persistent. It will survive restarts and relogins.

After the initial setup (that you just did), if you want to reflect any changes in your ~/.bash_profile to your whole environment again, rerunning the launchctl load ... command won't perform what you want; instead you'll get a warning like the following:

<$HOME>/Library/LaunchAgents/osx-env-sync.plist: Operation already in progress

In order to reload your environment variables without going through the logout/login process do the following:

launchctl unload ~/Library/LaunchAgents/osx-env-sync.plist
launchctl load ~/Library/LaunchAgents/osx-env-sync.plist

Finally make sure that you relaunch your already running applications (including Terminal.app) to make them aware of the changes.

I've also pushed the code and explanations here to a GitHub project: osx-env-sync.

I hope this is going to be the ultimate solution, at least for the latest versions of OS X (Yosemite & El Capitan).

Stepan Vavra
  • 3,884
  • 5
  • 29
  • 40
Ersin Er
  • 1,025
  • 7
  • 10
  • Works nicely. Slightly worried if this became popular if it would be a security loophole – Warren P Sep 07 '15 at 19:16
  • 4
    This solution was the only one I could get to work properly. Great solutions. I can't understand why this should be so hard on mac... – JohnyTex Dec 29 '15 at 19:25
  • 2
    This doesn't work on El Capitan, unfortunately. Your comment from https://github.com/ersiner/osx-env-sync/issues/1#issuecomment-169803508 explains the problem well. – mgol Jan 20 '16 at 13:00
  • 3
    So, this solution doesn't work, /etc/launchd.conf has no effect, Node.js installs its binary to /usr/local/bin and this path is not in PATH for GUI apps. Therefore, Git hooks using Node don't work in GUI Git apps like SourceTree at all in El Capitan. This is terrible. – mgol Jan 20 '16 at 13:01
  • 1
    The problem is only about the PATH variable. I hope we can find a solution soon. – Ersin Er Jan 22 '16 at 18:57
  • I'm running version 10.11.3 (15D21), and this is working for me as of 02/18/2016. This was such a headache to figure out that I was missing Windows for a while there! Thank you for this solution. – Steve Gelman Feb 19 '16 at 15:20
  • @m_gol For `$PATH`, use `launchctl config user path ` instead. – Franklin Yu May 22 '17 at 02:04
  • Before testing this via `env` or other command line command, make sure you restart your terminal(s). I was using iTerm2 and I was just launching new shell tabs, which was not enough: I had to restart the whole iTerm2 before changes were visible. – Danijel Sep 30 '19 at 08:54
  • 1
    Could the `launchctl setenv ...` commands not just go straight into your `~/.bash_profile`, and then they would be run on login? – SpinUp __ A Davis Jul 07 '22 at 09:58
61
  1. Do:

    vim ~/.bash_profile
    

    The file may not exist (if not, you can just create it).

  2. Type in this and save the file:

    export PATH=$PATH:YOUR_PATH_HERE
    
  3. Run

    source ~/.bash_profile
    
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
WoooHaaaa
  • 19,732
  • 32
  • 90
  • 138
  • +1 `export` is what I was going to suggest, since BASH doesn't support `setenv` – vol7ron Jun 10 '12 at 23:17
  • Works for now. This whole thing looks a lot more complicated than I thought. Will have to dedicate some more time for all these later. Thanks. – Kaka Ruto Aug 02 '19 at 19:39
36

There are essentially two problems to solve when dealing with environment variables in OS X. The first is when invoking programs from Spotlight (the magnifying glass icon on the right side of the Mac menu/status bar) and the second when invoking programs from the Dock. Invoking programs from a Terminal application/utility is trivial because it reads the environment from the standard shell locations (~/.profile, ~/.bash_profile, ~/.bashrc, etc.)

When invoking programs from the Dock, use ~/.MacOSX/environment.plist where the <dict> element contains a sequence of <key>KEY</key><string>theValue</string> elements.

When invoking programs from Spotlight, ensure that launchd has been setup with all the key/value settings you require.

To solve both problems simultaneously, I use a login item (set via the System Preferences tool) on my User account. The login item is a bash script that invokes an Emacs lisp function although one can of course use their favorite scripting tool to accomplish the same thing. This approach has the added benefit that it works at any time and does not require a reboot, i.e. one can edit ~/.profile, run the login item in some shell and have the changes visible for newly invoked programs, from either the Dock or Spotlight.

Details:

Login item: ~/bin/macosx-startup

#!/bin/bash
bash -l -c "/Applications/Emacs.app/Contents/MacOS/Emacs --batch -l ~/lib/emacs/elisp/macosx/environment-support.el -f generate-environment"

Emacs lisp function: ~/lib/emacs/elisp/macosx/envionment-support.el

;;; Provide support for the environment on Mac OS X

(defun generate-environment ()
  "Dump the current environment into the ~/.MacOSX/environment.plist file."
  ;; The system environment is found in the global variable:
  ;; 'initial-environment' as a list of "KEY=VALUE" pairs.
  (let ((list initial-environment)
        pair start command key value)
    ;; clear out the current environment settings
    (find-file "~/.MacOSX/environment.plist")
    (goto-char (point-min))
    (setq start (search-forward "<dict>\n"))
    (search-forward "</dict>")
    (beginning-of-line)
    (delete-region start (point))
    (while list
      (setq pair (split-string (car list) "=")
            list (cdr list))
      (setq key (nth 0 pair)
            value (nth 1 pair))
      (insert "  <key>" key "</key>\n")
      (insert "  <string>" value "</string>\n")

      ;; Enable this variable in launchd
      (setq command (format "launchctl setenv %s \"%s\"" key value))
      (shell-command command))
    ;; Save the buffer.
    (save-buffer)))

NOTE: This solution is an amalgam of those coming before I added mine, particularly that offered by Matt Curtis, but I have deliberately tried to keep my ~/.bash_profile content platform independent and put the setting of the launchd environment (a Mac only facility) into a separate script.

dcow
  • 7,765
  • 3
  • 45
  • 65
pajato0
  • 3,628
  • 3
  • 31
  • 37
  • 25
    Wow. I'm not saying this won't work, but ... I'm just appalled at the complexity required to get a consistent environment on OS X. – offby1 Jun 07 '13 at 17:00
  • 2
    This works the best out of all the solutions I've seen for 10.9. The only flaw is that, since login items run in an indeterminate order, if Emacs (for example) is launched at login (because it was open at logout, for example), it won't necessarily have the environment variables unless you restart it, because it's launched before your script is. – telotortium Jan 06 '14 at 08:05
24

Another, free, opensource, Mac OS X v10.8 (Mountain Lion) Preference pane/environment.plist solution is EnvPane.

EnvPane's source code available on GitHub. EnvPane looks like it has comparable features to RCEnvironment, however, it seems it can update its stored variables instantly, i.e. without the need for a restart or login, which is welcome.

As stated by the developer:

EnvPane is a preference pane for Mac OS X 10.8 (Mountain Lion) that lets you set environment variables for all programs in both graphical and terminal sessions. Not only does it restore support for ~/.MacOSX/environment.plist in Mountain Lion, it also publishes your changes to the environment immediately, without the need to log out and back in. <SNIP> EnvPane includes (and automatically installs) a launchd agent that runs 1) early after login and 2) whenever the ~/.MacOSX/environment.plist changes. The agent reads ~/.MacOSX/environment.plist and exports the environment variables from that file to the current user's launchd instance via the same API that is used by launchctl setenv and launchctl unsetenv.

Disclaimer: I am in no way related to the developer or his/her project.

P.S. I like the name (sounds like 'Ends Pain').

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Big Rich
  • 5,864
  • 1
  • 40
  • 64
  • 2
    EnvPane can't set PATH at the moment. For more details see my bug report: github.com/hschmidt/EnvPane/issues/5 – Uwe Günther Mar 25 '13 at 04:39
  • I ♥️ this thing.. Only drawback.. which I think _ANY solution will be a victim of_.. is - having to restart a process - to inherit the new "environment". Wonk wonk. – Alex Gray May 07 '14 at 23:16
  • 2
    @sorin: Can you open an issue on the GitHub site with a description of the problem you are experiencing? EnvPane works for me on 10.10. Disclaimer: I am the author of EnvPane. – Hannes Mar 27 '15 at 18:52
18

On Mountain Lion all the /etc/paths and /etc/launchd.conf editing doesn't make any effect!

Apple's Developer Forums say:

"Change the Info.plist of the .app itself to contain an "LSEnvironment" dictionary with the environment variables you want.

~/.MacOSX/environment.plist is no longer supported."

So I directly edited the application's Info.plist (right click on "AppName.app" (in this case SourceTree) and then "Show package contents").

Show Package Contents

And I added a new key/dict pair called:

<key>LSEnvironment</key>
<dict>
     <key>PATH</key>
     <string>/Users/flori/.rvm/gems/ruby-1.9.3-p362/bin:/Users/flori/.rvm/gems/ruby-1.9.3-p362@global/bin:/Users/flori/.rvm/rubies/ruby-1.9.3-p326/bin:/Users/flori/.rvm/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:</string>
</dict>

(see: LaunchServicesKeys Documentation at Apple)

Enter image description here

Now the application (in my case Sourcetree) uses the given path and works with Git 1.9.3 :-)

PS: Of course you have to adjust the Path entry to your specific path needs.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Flori
  • 2,453
  • 1
  • 21
  • 31
  • 3
    This solution meets the standard of least intrusive on the system. Thanks. – John Vance Sep 09 '13 at 19:29
  • @John Vance +1 Totally agree, system-wide changes are always risky as Jason T. Miller explains clearly in his answer – rmcsharry Jun 22 '14 at 04:42
  • 5
    It has no effect for me in El Capitan. :( – mgol Jan 20 '16 at 12:46
  • On High Sierra 10.13, if I modify application's `Info.plist` file then the application fails to load: `LSOpenURLsWithRole() failed with error -10810 for the file /Applications/Slack.app.` – kunjbhai May 13 '20 at 04:43
17

Update (2017-08-04)

As of (at least) macOS 10.12.6 (Sierra) this method seems to have stopped working for Apache httpd (for both the system and the user option of launchctl config). Other programs do not seem to be affected. It is conceivable that this is a bug in httpd.

Original answer

This concerns OS X 10.10+ (10.11+ specifically due to rootless mode where /usr/bin is no longer writeable).

I've read in multiple places that using launchctl setenv PATH <new path> to set the PATH variable does not work due to a bug in OS X (which seems true from personal experience). I found that there's another way the PATH can be set for applications not launched from the shell:

sudo launchctl config user path <new path>

This option is documented in the launchctl man page:

config system | user parameter value

Sets persistent configuration information for launchd(8) domains. Only the system domain and user domains may be configured. The location of the persistent storage is an implementation detail, and changes to that storage should only be made through this subcommand. A reboot is required for changes made through this subcommand to take effect.

[...]

path

Sets the PATH environment variable for all services within the target domain to the string value. The string value should conform to the format outlined for the PATH environment variable in environ(7). Note that if a service specifies its own PATH, the service-specific environment variable will take precedence.

NOTE: This facility cannot be used to set general environment variables for all services within the domain. It is intentionally scoped to the PATH environment vari- able and nothing else for security reasons.

I have confirmed this to work with a GUI application started from Finder (which uses getenv to get PATH). Note that you only have to do this once and the change will be persistent through reboots.

Max Leske
  • 5,007
  • 6
  • 42
  • 54
  • It works for me, too. `sudo launchctl procinfo ` shows newly set `PATH` environment. But `sudo launchctl config user path ` actually set for all users... (confirmed by adding new user & using Sublime Text's python console) – Bossliaw May 18 '16 at 14:58
  • 1
    This doesn't seem to have an effect on the PATH environment variable of applications that are reopened at login (that were open when shutting down). – Brecht Machiels Jul 08 '16 at 14:32
  • Interesting. That would mean that for applications that will be reopened the environment (or a subset thereof) is being saved. – Max Leske Jul 08 '16 at 15:38
  • @MaxLeske No, the reopened applications are being started before the environment variable is changed. So, it's not just the first time after doing `sudo launchctl config user path`, that this happens (which you seem to be assuming?). – Brecht Machiels Jul 31 '16 at 11:27
  • Well, there's something weird going on here. But it's just too much of a black box. Potentially, an application could just be initialising it's environment variables wrongly (e.g. assigning to PATH without preserving the original value). – Max Leske Jul 31 '16 at 14:18
  • Could you please elaborate with a short example? Let's say I want to add an environment var named FOO with value BAR – Shlomi Schwartz Aug 30 '17 at 10:14
  • 1
    @ShlomiSchwartz `launchctl` does *not* allow you to set arbitrary environment variables. The `PATH` variable is an exception. – Max Leske Aug 30 '17 at 18:31
  • @ShlomiSchwartz as per https://ss64.com/osx/launchctl.html, only `umask` and `path` can be set like this. – kunjbhai May 13 '20 at 03:06
15

While the answers here aren't "wrong", I'll add another: never make environment variable changes in OS X that affect "all processes", or even, outside the shell, for all processes run interactively by a given user.

In my experience, global changes to environment variables like PATH for all processes are even more likely to break things on OS X than on Windows. Reason being, lots of OS X applications and other software (including, perhaps especially, components of the OS itself) rely on UNIX command-line tools under the hood, and assume the behavior of the versions of these tools provided with the system, and don't necessarily use absolute paths when doing so (similar comments apply to dynamically-loaded libraries and DYLD_* environment variables). Consider, for instance, that the highest-rated answers to various Stack Overflow questions about replacing OS X-supplied versions of interpreters like Python and Ruby generally say "don't do this."

OS X is really no different than other UNIX-like operating systems (e.g., Linux, FreeBSD, and Solaris) in this respect; the most likely reason Apple doesn't provide an easy way to do this is because it breaks things. To the extent Windows isn't as prone to these problems, it's due to two things: (1) Windows software doesn't tend to rely on command-line tools to the extent that UNIX software does, and (2) Microsoft has had such an extensive history of both "DLL hell" and security problems caused by changes that affect all processes that they've changed the behavior of dynamic loading in newer Windows versions to limit the impact of "global" configuration options like PATH.

"Lame" or not, you'll have a far more stable system if you restrict such changes to smaller scopes.

Jason T. Miller
  • 672
  • 7
  • 7
  • 1
    Telling people not to do the thing they asked how to do is not an answer to the question they asked. Preventing people from doing this is also breaking things. Apple's modus operandi. – frabjous Sep 04 '19 at 21:10
  • Setting the PATH in /Applications/App.app/Contents/Info.plist with the LSEnvironment key https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/20001431-106825 might be the current recommended solution. – Dave X May 15 '20 at 02:37
  • 1
    @DaveX No, it definitely isn’t. You *mustn’t* modify the contents of an app bundle. Doing so can cause the app to fail to launch (even if the configuration is correct!) because the contents no longer match the code signature. – Konrad Rudolph Mar 23 '21 at 19:07
15

Sometimes all of the previous answers simply don't work. If you want to have access to a system variable (like M2_HOME) in Eclipse or in IntelliJ IDEA the only thing that works for me in this case is:

First (step 1) edit /etc/launchd.conf to contain a line like this: "setenv VAR value" and then (step 2) reboot.

Simply modifying .bash_profile won't work because in OS X the applications are not started as in other Unix'es; they don't inherit the parent's shell variables. All the other modifications won't work for a reason that is unknown to me. Maybe someone else can clarify about this.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bruno Ranschaert
  • 7,428
  • 5
  • 36
  • 46
  • 5
    Applications started from Spotlight or by any other means all have /etc/launchd.conf read by their parent process, thus making that an appealing choice for where to set environment variables visible in all apps and shells. – Matthew McCullough Feb 26 '09 at 03:51
  • 1
    See my answer for another solution, which avoids a reboot - http://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x/3756686#3756686 – Matt Curtis Sep 29 '10 at 03:24
  • My MaxOS 10.6 machine does not have the /etc/launchd.conf file present. Is this either a new or an obsolete thing as of this version ? Or is this machine messed up ? – peterk Oct 09 '11 at 23:41
13

After chasing the Environment Variables preference pane and discovering that the link is broken and a search on Apple's site seems to indicate they've forgotten about it... I started back onto the trail of the elusive launchd process.

On my system (Mac OS X 10.6.8) it appears that variables defined in environment.plist are being reliably exported to apps launched from Spotlight (via launchd). My trouble is that those vars are not being exported to new bash sessions in Terminal. I.e. I have the opposite problem as portrayed here.

NOTE: environment.plist looks like JSON, not XML, as described previously

I was able to get Spotlight apps to see the vars by editing ~/MacOSX/environment.plist and I was able to force the same vars into a new Terminal session by adding the following to my .profile file:

eval $(launchctl export)
Russell B
  • 891
  • 9
  • 13
  • 2
    Not that elusive: [RCenvironment](http://www.rubicode.com/Software/RCEnvironment/) – Gilimanjaro Oct 26 '11 at 13:15
  • Nice tip about launchctl export. But I wouldn't put that as-is into .profile. It will overwrite your $PATH with one that doesn't include /usr/local/bin. But you can use a regex to select the vars you are interested in: ``eval $(launchctl export | grep '^my.*='). – mivk Jul 12 '12 at 17:13
  • 3
    On my new Mountain Lion machine (10.8.2) the environment.plist is completely worthless. See Matthew's answer for the right track. It's all about launched and the launchctl command-line app along with /etc/launchd.conf. You can read up yourself with `man launchd`, `man launchctl`, and `man launchd.conf` in a terminal window. Glad Apple keeps the man pages up to date, even if the Mac Developer Library lags a bit. – Russell B Jan 18 '13 at 22:39
11

Any of the Bash startup files -- ~/.bashrc, ~/.bash_profile, ~/.profile. There's also some sort of weird file named ~/.MacOSX/environment.plist for environment variables in GUI applications.

John Millikin
  • 197,344
  • 39
  • 212
  • 226
11

Here is a very simple way to do what you want. In my case, it was getting Gradle to work (for Android Studio).

  • Open up Terminal.
  • Run the following command:

    sudo nano /etc/paths or sudo vim /etc/paths

  • Enter your password, when prompted.

  • Go to the bottom of the file, and enter the path you wish to add.
  • Hit Control + X to quit.
  • Enter 'Y' to save the modified buffer.
  • Open a new terminal window then type:

    echo $PATH

You should see the new path appended to the end of the PATH.

I got these details from this post:

Add to the PATH on Mac OS X 10.8 Mountain Lion and up

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wired00
  • 13,930
  • 7
  • 70
  • 73
11

Much like the answer Matt Curtis gave, I set environment variables via launchctl, but I wrap it in a function called export, so that whenever I export a variable like normal in my .bash_profile, it is also set by launchctl. Here is what I do:

  1. My .bash_profile consists solely of one line, (This is just personal preference.)

    source .bashrc
    
  2. My .bashrc has this:

    function export()
    {
        builtin export "$@"
        if [[ ${#@} -eq 1 && "${@//[^=]/}" ]]
        then
            launchctl setenv "${@%%=*}" "${@#*=}"
        elif [[ ! "${@//[^ ]/}" ]]
        then
            launchctl setenv "${@}" "${!@}"
        fi
    }
    
    export -f export
    
  3. The above will overload the Bash builtin "export" and will export everything normally (you'll notice I export "export" with it!), then properly set them for OS X app environments via launchctl, whether you use any of the following:

    export LC_CTYPE=en_US.UTF-8
    # ~$ launchctl getenv LC_CTYPE
    # en_US.UTF-8
    PATH="/usr/local/bin:${PATH}"
    PATH="/usr/local/opt/coreutils/libexec/gnubin:${PATH}"
    export PATH
    # ~$ launchctl getenv PATH
    # /usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
    export CXX_FLAGS="-mmacosx-version-min=10.9"
    # ~$ launchctl getenv CXX_FLAGS
    # -mmacosx-version-min=10.9
    
  4. This way I don't have to send every variable to launchctl every time, and I can just have my .bash_profile / .bashrc set up the way I want. Open a terminal window, check out your environment variables you're interested in with launchctl getenv myVar, change something in your .bash_profile/.bashrc, close the terminal window and re-open it, check the variable again with launchctl, and voilá, it's changed.

  5. Again, like the other solutions for the post-Mountain Lion world, for any new environment variables to be available for apps, you need to launch or re-launch them after the change.

courtlandj
  • 435
  • 9
  • 19
  • 1
    Useful answer - thanks. I just updated it because your original solution didn't handle cases where the value of the environment variable you were setting had equals signs in it (e.g., CXX_FLAGS="-mmacosx-version-min=10.9" – Steve Broberg Jan 23 '15 at 01:07
  • @SteveBroberg - just a one character change fixes up the Bash regexp without needing sed! (Don't get me wrong, I love sed, but this works and is a lot shorter.) – courtlandj Feb 02 '15 at 22:29
  • 1
    I figured there had to be a better way, but I'm not a bash guru, and I couldn't google what %%, ## were, etc. – Steve Broberg Feb 03 '15 at 18:56
9

I think the OP is looking for a simple, Windows-like solution.

Here you go:

http://www.apple.com/downloads/macosx/system_disk_utilities/environmentvariablepreferencepane.html

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tom Teman
  • 1,975
  • 3
  • 28
  • 43
9

Feb 2022 (MacOs 12+)

Solutions here should work after reboot or application restart.

CLI

Open your CLI of choice config file.

  • For bash open ~/.bash_profile
  • For zsh open ~/.zshrc

add (or replace)

export varName=varValue 

(if varValue has spaces in it - wrap it in ")

Make sure to restart command line app.

GUI

Complete the CLI step. Make sure GUI app is closed. Open GUI app from the command line. For example:

open /Applications/Sourcetree.app

(you can also alias this command in the .zshrc)

Principles

  • Mac does not have a configuration options that sets environment variable for all contexts.
  • Avoid changing anything outside your user profile.

Doesn't work anymore

  • launchctl config user varName varVal (MacOS 12.1+)
  • Editing /etc/launchd.conf
  • xml file with plist suffix
Ben Carp
  • 24,214
  • 9
  • 60
  • 72
  • Is it possible to set environment variables for a specific launchd service? – Philippe Apr 13 '22 at 11:41
  • This answer would be more helpful if it included something like "if the file doesn't exist, write 'touch' prior to such as 'touch ~/.zshrc' and then 'open ~/.zshrc'". :) – Adam Bridges Oct 20 '22 at 18:48
  • @AdamBridges you mean - if `~/.bash_profile` or `~/.zshrc` don't exist? – Ben Carp Oct 22 '22 at 16:57
  • @BenCarp Yes, sir! – Adam Bridges Oct 24 '22 at 23:08
  • I think that if you use `zshrc` it is unlikely that `.zshrc` doesn't exist. Not sure about `.bash_profile`. – Ben Carp Oct 25 '22 at 04:30
  • @BenCarp I had to create my zshrc file after I configured terminal to use zsh. Newer Macs probably already have this configured by default; whereas, I am using a 2014 mac mini. – Adam Bridges Oct 26 '22 at 20:08
  • `launchctl setenv varName varVal` does still work in Monterey but doesn't survive reboots. You can create a LaunchAgent that takes care of this. When doing so, you can process a full `~/.launchd.conf` file like outlined in [this comment](https://stackoverflow.com/a/4567308/5805552) or implemented as a nice [helper script](https://github.com/yuezk/macenv) – tbussmann Nov 21 '22 at 18:29
7

To be concise and clear about what each file is intended for

  • ~/.profile is sourced every time Terminal.app is launched
  • ~/.bashrc is where "traditionally" all the export statements for Bash environment are set
  • /etc/paths is the main file in Mac OS that contains the list of default paths for building the PATH environment variable for all users
  • /etc/paths.d/ contains files that hold additional search paths

Non-terminal programs don't inherit the system wide PATH and MANPATH variables that your terminal does! To set environment for all processes launched by a specific user, thus making environment variables available to Mac OS X GUI applications, those variables must be defined in your ~/.MacOSX/environment.plist (Apple Technical Q&A QA1067)

Use the following command line to synchronize your environment.plist with /etc/paths:

defaults write $HOME/.MacOSX/environment PATH "$(tr '\n' ':' </etc/paths)"
Claudio Floreani
  • 2,441
  • 28
  • 34
  • /etc/paths.d/ was the method I was looking for, as I was trying to understand why every process I started had a particular directory of an installed component in the PATH environment on my machine, but it wasn't working correctly on another. Turns out it was in a file under /etc/paths.d, which /usr/libexec/path_helper uses to construct the PATH environment variable when starting new processes. – Dylan Nicholson May 10 '22 at 09:29
7

The $PATH variable is also subject to path_helper, which in turn makes use of the /etc/paths file and files in /etc/paths.d.

A more thorough description can be found in PATH and other environment issues in Leopard (2008-11)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nicolas Wu
  • 4,805
  • 2
  • 25
  • 32
6

/etc/launchd.conf is not used in OS X v10.10 (Yosemite), OS X v10.11 (El Capitan), macOS v10.12 (Sierra), or macOS v10.13 (High Sierra).


From the launchctl man page:

/etc/launchd.conf file is no longer consulted for subcommands to run during early boot time;
this functionality was removed for security considerations.

The method described in this Ask Different answer works for me (after a reboot): applications launched from the Dock or from Spotlight inherit environment variables that I set in ~/Library/LaunchAgents/my.startup.plist. (In my case, I needed to set LANG, to en_US.UTF-8, for a Sublime Text plugin.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David
  • 1,167
  • 15
  • 24
  • On reboot is there a load order that ensures my.startup.plist would have been loaded before applications from last session are restarted? – kunjbhai May 13 '20 at 03:01
5

Just did this really easy and quick. First create a ~/.bash_profile from terminal:

touch .bash_profile

then

open -a TextEdit.app .bash_profile

add

export TOMCAT_HOME=/Library/Tomcat/Home

save documement and you are done.

CodeOverRide
  • 4,431
  • 43
  • 36
4

All the magic on iOS only goes with using source with the file, where you export your environment variables.

For example:

You can create an file like this:

export bim=fooo
export bom=bar

Save this file as bimbom.env, and do source ./bimbom.ev. Voilá, you got your environment variables.

Check them with:

echo $bim
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
suther
  • 12,600
  • 4
  • 62
  • 99
3

For a single user modification, use ~/.profile of the ones you listed. The following link explains when the different files are read by Bash.

http://telin.ugent.be/~slippens/drupal/bashrc_and_others

If you want to set the environment variable for gui applications you need the ~/.MacOSX/environment.plist file

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mmaibaum
  • 2,379
  • 13
  • 11
3

Well, I'm unsure about the /etc/paths and ~/.MacOSX/environment.plist files. Those are new.

But with Bash, you should know that .bashrc is executed with every new shell invocation and .bash_profile is only executed once at startup.

I don't know how often this is with Mac OS X. I think the distinction has broken down with the window system launching everything.

Personally, I eliminate the confusion by creating a .bashrc file with everything I need and then do:

ln -s .bashrc .bash_profile
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mike511
  • 1,685
  • 4
  • 16
  • 18
3

Set up your PATH environment variable on Mac OS

Open the Terminal program (this is in your Applications/Utilities folder by default). Run the following command

touch ~/.bash_profile; open ~/.bash_profile

This will open the file in the your default text editor.

For Android SDK as example:

You need to add the path to your Android SDK platform-tools and tools directory. In my example I will use "/Development/android-sdk-macosx" as the directory the SDK is installed in. Add the following line:

export PATH=${PATH}:/Development/android-sdk-macosx/platform-tools:/Development/android-sdk-macosx/tools

Save the file and quit the text editor. Execute your .bash_profile to update your PATH:

source ~/.bash_profile

Now every time you open the Terminal program your PATH will include the Android SDK.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Charaf JRA
  • 8,249
  • 1
  • 34
  • 44
3

It's simple:

Edit ~/.profile and put your variables as follow

$ vim ~/.profile

In file put:

MY_ENV_VAR=value

  1. Save ( :wq )

  2. Restart the terminal (Quit and open it again)

  3. Make sure that`s all be fine:

$ echo $MY_ENV_VAR

$ value


Fernando Martínez
  • 1,057
  • 10
  • 13
3

It's quite simple. Edit file .profile (vi, nano, Sublime Text or other text editor) file. You can found it at the ~/ directory (user directory) and set like this:

export MY_VAR=[your value here]

Example with Java home:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/current

Save it and return to the terminal.

You can reload it with:

source .profile

Or close and open your terminal window.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3

One thing to note in addition to the approaches suggested is that, in OS X 10.5 (Leopard) at least, the variables set in launchd.conf will be merged with the settings made in .profile. I suppose this is likely to be valid for the settings in ~/.MacOSX/environment.plist too, but I haven't verified.

MiB
  • 575
  • 2
  • 10
  • 26
2

There are two type of shells at play here.

  • Non-login: .bashrc is reloaded every time you start a new copy of Bash
  • Login: The .profile is loaded only when you either login, or explicitly tell Bash to load it and use it as a login shell.

It's important to understand here that with Bash, file .bashrc is only read by a shell that's both interactive and non-login, and you will find that people often load .bashrc in .bash_profile to overcome this limitation.

Now that you have the basic understanding, let’s move on to how I would advice you to set it up.

  • .profile: create it non-existing. Put your PATH setup in there.
  • .bashrc: create if non-existing. Put all your aliases and custom methods in there.
  • .bash_profile: create if non-existing. Put the following in there.

.bash_file:

#!/bin/bash
source ~/.profile # Get the PATH settings
source ~/.bashrc  # Get Aliases and Functions
#
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ZOXIS
  • 578
  • 5
  • 15
2

Login Shells

/etc/profile

The shell first executes the commands in file /etc/profile. A user working with root privileges can set up this file to establish systemwide default characteristics for users running Bash.

.bash_profile
.bash_login
.profile

Next the shell looks for ~/.bash_profile, ~/.bash_login, and ~/.profile (~/ is short- hand for your home directory), in that order, executing the commands in the first of these files it finds. You can put commands in one of these files to override the defaults set in /etc/profile. A shell running on a virtual terminal does not execute commands in these files.

.bash_logout

When you log out, bash executes commands in the ~/.bash_logout file. This file often holds commands that clean up after a session, such as those that remove temporary files.

Interactive Nonlogin Shells

/etc/bashrc

Although not called by bash directly, many ~/.bashrc files call /etc/bashrc. This setup allows a user working with root privileges to establish systemwide default characteristics for nonlogin bash shells.

.bashrc

An interactive nonlogin shell executes commands in the ~/.bashrc file. Typically a startup file for a login shell, such as .bash_profile, runs this file, so both login and nonlogin shells run the commands in .bashrc.

Because commands in .bashrc may be executed many times, and because subshells inherit exported variables, it is a good idea to put commands that add to existing variables in the .bash_profile file.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
0

My personal practice is .bash_profile. I'm adding paths there and append to Path variable,

GOPATH=/usr/local/go/bin/
MYSQLPATH=/usr/local/opt/mysql@5.6/bin

PATH=$PATH:$GOPATH:$MYSQLPATH

After then I can have individual Path by echo $GOPATH, echo$MYSQLPATH or all by echo $PATH.

Thushara Buddhika
  • 1,652
  • 12
  • 14
0

For Bash, try adding your environment variables to the file /etc/profile to make them available for all users. No need to reboot, just start a new Terminal session.

Rabi
  • 2,593
  • 1
  • 23
  • 26
-1

For macOS Ventura (13.3.1)

After some back and forth between this thread and ChatGPT, ChatGPT suggested a solution that worked for me :). The custom environment variable can be seen by other applications. This is regardless of how they get started (terminal, icon on desktop or spotlight search) and it still works after restarting macOS.

My use case: I'm running JetBrains Rider on macOS Ventura und have a Plugin called PlantUML, which requires to find the "dot" executable of GraphViz in a certain file location OR an environment variable "GRAPHVIZ_DOT" pointing towards the location. I chose the later option.

Following is the step by step guid from ChatGPT:

  1. Open Terminal on your macOS Ventura system.

  2. Execute the following command to create a launch agent plist file:

     nano ~/Library/LaunchAgents/setenv.VARIABLE_NAME.plist
    

This command will open the nano text editor with a new file.

  1. In the nano editor, add the following XML code to the file:

     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0">
     <dict>
         <key>Label</key>
         <string>setenv.VARIABLE_NAME</string>
         <key>ProgramArguments</key>
         <array>
             <string>/usr/bin/env</string>
             <string>VARIABLE_NAME=variable_value</string>
             <string>launchctl</string>
             <string>setenv</string>
             <string>VARIABLE_NAME</string>
             <string>variable_value</string>
         </array>
         <key>RunAtLoad</key>
         <true/>
     </dict>
     </plist>
    

Replace VARIABLE_NAME with the actual name you want to use for your environment variable, and replace variable_value with the desired value.

  1. Press "Ctrl + O" to save the file, then press "Enter" to confirm the filename. Finally, press "Ctrl + X" to exit the nano editor.

  2. Execute the following command to load the launch agent:

     launchctl load ~/Library/LaunchAgents/setenv.VARIABLE_NAME.plist
    
  3. Restart your macOS system.

By using launchctl, the environment variable should be set globally and persist across system restarts. This should make it available to all applications, including JetBrains Rider, regardless of how you launch them.

For my use case:
VARIABLE_NAME = GRAPHVIZ_DOT
variable_value = /opt/homebrew/Cellar/graphviz/8.0.5/bin/dot

Hope it helps.

Bredjo
  • 19
  • 6