MacOS – In OSX Yosemite, why can I set many environment variables for GUI apps, but cannot set the specific variable PATH

environment-variableslaunchdmacospath

After I had sorted out OSX' PATH issues up to the Mavericks release, the problems come back in Yosemite!!!

So I want to mimic the old launch.conf feature in the new Mac OSX 10.10 Yosemite release, in order to have the PATH environment variable in GUI apps like Carbon Emacs or RStudio available. I used the great idea of stackoverflow user ursa to set up a shell script which configures environment variables via launchctl. (See his stackoverflow answer here.) This works for most environment variables, but not for the PATH variable.

1. What have I done?

First I wrote the /etc/environment.rc script looking like:

launchctl setenv PATH /Users/halloleo/bin:/usr/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
launchctl setenv JAVA_HOME /usr/local/jdk1.7
launchctl setenv ENVIRONMENT_RC "yes"

Then I created the plists for launchd (listings of these and of other mentioned scripts in the appendix below). Then I activated them with

$ sudo launchctrl load ...

Then I disabled the path_helper utility in shell init file /etc/profile, so that it does not overwrite the environment.rc settings. And finally I restarted the machine.

2. What's the effect?

When I start up Terminal the new environment variables JAVA_HOME and ENVIRONMENT_RC are set according to environment.rc, but PATH is set to

/usr/bin:/bin

In order to make sure, no bash init file got in the way I wrote a little python script instead (in the appendix as well) to show the variables in the current environment and I execute this directly by double clicking a Platypus wrapper. Again the new variables are set, while PATH has the system default.

So why can I set other variables, but not the PATH variable? And how can I solve this in a unified way?

Update:

The situation is very puzzling: The shell (bash at least) in Terminal or Emacs will pick up the PATH you set via launchctl, but other GUI apps will not do so., e.g. the mentioned minimal python script straight called via Platypus will not show your custom path. And even Emacs itself does not know the correct PATH: You notice this e.g. when you issue the Emacs command M-x ispell-buffer; the unix tool ispell which emacs tries to call won't be found if it is just on your custom path.


Appendix

net.halloleo.environment.plist, the launchd config file in /Library/LaunchDaemons/:

<?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>KeepAlive</key>
    <false/>
    <key>Label</key>
    <string>net.halloleo.environment</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/sh</string>
        <string>/etc/environment.rc</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/etc/environment.rc</string>
    </array>
</dict>
</plist>

net.halloleo.environment-user.plist, the launchd config file in /Library/LaunchAgents/:

<?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>KeepAlive</key>
    <false/>
    <key>Label</key>
    <string>net.halloleo.environment-user</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/sh</string>
        <string>/etc/environment.rc</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/etc/environment.rc</string>
    </array>
</dict>
</plist>

/etc/profile, the modified bash start-up file:

# System-wide .profile for sh(1)

# if [ -x /usr/libexec/path_helper ]; then
#   eval `/usr/libexec/path_helper -s`
# fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

show_environ.py, the script displaying all environment variables:

import os
print (os.environ)

Best Answer

PATH in Yosemite can and should be set within /etc/paths file. Just add your path to the end of this file:

/usr/bin
/bin
/your/custom/path

/etc/environment script in original post provides support for PATH variable in GUI applications (tested with Emacs).