Update: The link below does not have a complete answer. Having to set the path or variable in two places (one for GUI and one for shell) is lame.
Not Duplicate of: Setting environment variables in OS X?
Coming from a Windows background where it's very easy to set and modify environment variables (just go to System Properties > Advanced > Environment Variables), it does not seem to be that straight forward on Mac OS 10.5. Most references say I should update /etc/profile or ~/.profile. Are those the equivalent of System Variables and User Variables? For example, where should I set my JAVA_HOME
variable?
EDIT:
I want to be able to access the variable from the terminal as well as an app like Eclipse. Also, I hope I don't have to restart/logout to make this take effect.
There are several places where you can set environment variables.
~/.profile: use this for variables you want to set in all programs launched from the terminal (note that, unlike on Linux, all shells opened in Terminal.app are login shells).
~/.bashrc: this is invoked for shells which are not login shells. Use this for aliases and other things which need to be redefined in subshells, not for environment variables that are inherited.
/etc/profile: this is loaded before ~/.profile, but is otherwise equivalent. Use it when you want the variable to apply to terminal programs launched by all users on the machine (assuming they use bash).
~/.MacOSX/environment.plist: this is read by loginwindow on login. It applies to all applications, including GUI ones, except those launched by Spotlight in 10.5 (not 10.6). It requires you to logout and login again for changes to take effect. This file is no longer supported as of OS X 10.8.
your user's launchd instance: this applies to all programs launched by the user, GUI and CLI. You can apply changes at any time by using the setenv command in launchctl. In theory, you should be able to put setenv commands in ~/.launchd.conf, and launchd would read them automatically when the user logs in, but in practice support for this file was never implemented. Instead, you can use another mechanism to execute a script at login, and have that script call launchctl to set up the launchd environment.
/etc/launchd.conf: this is read by launchd when the system starts up and when a user logs in. They affect every single process on the system, because launchd is the root process. To apply changes to the running root launchd you can pipe the commands into sudo launchctl.
The fundamental things to understand are:
environment variables are inherited by a process's children at the time they are forked.
the root process is a launchd instance, and there is also a separate launchd instance per user session.
launchd allows you to change its current environment variables using launchctl; the updated variables are then inherited by all new processes it forks from then on.
Example of setting an environment variable with launchd:
echo setenv REPLACE_WITH_VAR REPLACE_WITH_VALUE | launchctl
Now, launch your GUI app that uses the variable, and voila!
To work around the fact that ~/.launchd.conf
does not work, you can put the following script in ~/Library/LaunchAgents/local.launchd.conf.plist
:
<?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>local.launchd.conf</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>-c</string>
<string>launchctl < ~/.launchd.conf</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Then you can put setenv REPLACE_WITH_VAR REPLACE_WITH_VALUE
inside ~/.launchd.conf
, and it will be executed at each login.
Note that, when piping a command list into launchctl in this fashion, you will not be able to set environment variables with values containing spaces. If you need to do so, you can call launchctl as follows: launchctl setenv MYVARIABLE "QUOTE THE STRING"
.
Also, note that other programs that run at login may execute before the launchagent, and thus may not see the environment variables it sets.
There's no need for duplication. You can set environment variables used by launchd (and child processes, i.e. anything you start from Spotlight) using launchctl setenv
.
For example, if you want to mirror your current path in launchd after setting it up in .bashrc
or wherever:
PATH=whatever:you:want
launchctl setenv PATH $PATH
Environment variables are not automatically updated in running applications. You will need to relaunch applications to get the updated environment variables (although you can just set variables in your shell, e.g. PATH=whatever:you:want
; there's no need to relaunch the terminal).
ps aux | grep launchd
will show this. Also check man sudo
, which documents that sudo
(by default) deliberately resets the environment - if you sudo -E
it will preserve the environment (including variables you've set with launchctl setenv
). Do you have an actual application for this, by the way? If so, does this method work for you?
launchctl config system path $PATH
will take care of root launchd. I believe launchctl config user path $PATH
would be the preferred way for to set a persistent path for user launchd. (vs setenv
).
I think what the OP is looking for is a simple, windows-like solution.
here ya go:
https://www.macupdate.com/app/mac/14617/rcenvironment
You can read up on linux, which is pretty close to what Mac OS X is. Or you can read up on BSD Unix, which is a little closer. For the most part, the differences between Linux and BSD don't amount to much.
/etc/profile
are system environment variables.
~/.profile
are user-specific environment variables.
"where should I set my JAVA_HOME variable?"
Do you have multiple users? Do they care? Would you mess some other user up by changing a /etc/profile?
Generally, I prefer not to mess with system-wide settings even though I'm the only user. I prefer to edit my local settings.
For GUI apps, you'll have to create and edit ~/.MacOSX/environment.plist
. More details here. You will need to log out for these to take effect. I'm not sure if they also affect applications launched from Terminal, but I assume they would.
For apps launched from Terminal, you can also edit the ~/.profile file.
Synchronize OS X environment variables for command line and GUI applications from a single source with osx-env-sync.
I also posted an answer to a related question here.
Just open the ~/.profile
file, via nano
in Terminal and type there :
export PATH=whatever/you/want:$PATH
Save this file (cmd+X and Y). After that please logout/login again or just open a new tab in Terminal and try use your new variable.
PLEASE DON'T forget to add ":$PATH" after whatever/you/want, otherwise you'll erase all paths in PATH variable, which were there before that.
I wrote a tool to make it easy to manage the environment variables for macOS applications.
https://github.com/yuezk/macenv
You can set the environment variable with ~/.macenv set
, for example:
~/.macenv set JAVA_HOME /path/to/java/home
Under the hood, it calls launchctl setenv
to set the environment variables, saves the environment variables to ~/.launchd.conf
at the same time, and registers an auto-start service to load the environment variables when OS restarts.
If you want to change environment variables permanently on macOS, set them in /etc/paths
. Note, this file is read-only by default, so you'll have to chmod for write permissions.
/usr/bin/local
in that file, even without modifying the file, it was that way by default, and yet my GUI apps see only /usr/bin:/bin:/usr/sbin:/sbin
. I rebooted many times.
cat /etc/paths/
?
For 2020 Mac OS X Catalina users:
Forget about other useless answers, here only two steps needed:
Create a file with the naming convention: priority-appname. Then copy-paste the path you want to add to PATH. E.g. 80-vscode with content /Applications/Visual Studio Code.app/Contents/Resources/app/bin/ in my case. Move that file to /etc/paths.d/. Don't forget to open a new tab(new session) in the Terminal and type echo $PATH to check that your path is added!
Notice: this method only appends your path to PATH
.
Success story sharing
~/.MacOSX/environment.plist
, on my Lion it is read and used. Just tested it. I actually prefer it over .launchd.conf because I use the RCenvironment preference pane to maintain it.~/.launchd.conf
to work on 10.6.8 - it doesn't appear to have any effect. Also man page says this file is currently unsupported.~/.launchd.conf
is still not supported and doesn't work as of OS X 10.8.3? Seeman launchd.conf