16

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)
3

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).

  • 5
    This does only work for shells which call /usr/libexec/path_helper during their initialisation process. GUI apps do not get the PATH according to /etc/paths - and I asked specifically about GUI apps. – halloleo Oct 28 '14 at 12:59
  • I've updated answer and /etc/environment script in original post – ursa Oct 28 '14 at 20:05
  • This is two answers which one are you giving - also the OP says /etc/environment does not work – Mark Oct 28 '14 at 20:30
  • @mark (1) after this question were rised I've updated /etc/environment, and now it does support PATH. (2) the answer here is to use /etc/paths – ursa Oct 28 '14 at 20:44
  • 2
    @mark Yes, and that is exactly my point, problem and question: How can I set the environment variable PATH of GUI apps themselves when launched via the Finder? Still, no real general solution for this in sight... – halloleo Nov 1 '14 at 0:46
2

This puzzled me for a long time (well, the last couple of hours). In the end I ran into this bug report, which seems to exactly describe my problem (I'm not sure to what extend it's related to your problem, but there seems to be a bug in Yosemite/launchd in combination with PATH and scripts such as python:

http://www.openradar.me/18945659

The solution seems to be to start a shell script which then starts the python. Not really what I like, but it's the way it is....

  • Thanks for the link to the bug report. Good to now it is a real bug. I found another clutch around it; I will post it here. – halloleo Jan 31 '15 at 0:07
1

The problem is that launchd appends another PATH variable instead of replacing the one in the environment. Most programs use getenv which always returns the first occurence of a variable, shells instead iterate through all environment variables and import them as local variables thus overwriting previous instances with the last one.

This is obviously a bug in launchd, environment variables passed to a program should be unique.

  • 1
    Cool background answer! I guess theer is not real way around it in shells, or is there? – halloleo Jun 25 '15 at 6:35
  • @halloleo You can launch the command as sh -c 'YOUR ORIGINAL COMMAND' which passes it though shell, picking the PATH set in launchd. – StenSoft Jun 25 '15 at 13:27

You must log in to answer this question.

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