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:
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.
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.
Use launchctl config user path /bin:/usr/bin:/mystuff
. See man launchctl
for more information.
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
.
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
").
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)
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.
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
It's simple:
Edit ~/.profile and put your variables as follow
$ vim ~/.profile
In file put:
MY_ENV_VAR=value
Save ( :wq )
Restart the terminal (Quit and open it again)
Make sure that`s all be fine:
$ echo $MY_ENV_VAR
$ value
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.
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.
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.