Setting environment variables in OS X for GUI applications
How does one set up environment variables in Mac OS X such that they are available for GUI applications without using ~/.MacOSX/environment.plist or Login Hooks (since these are deprecated)?
Solution 1:
On Mountain Lion all the /etc/paths
and /etc/launchd.conf
editing doesn't take 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 app's Info.plist
(right click on "AppName.app" (in this case SourceTree) and then "Show package contents
")
and 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 App (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.
Solution 2:
The solution uses the functionality of launchctl
, combined with a Launch Agent to mimic the login hooks of old. For other solutions using the store of launchd
, see this comparison.
The launch agent used here is located 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>Label</key>
<string>user.conf.launchd</string>
<key>Program</key>
<string>/Users/Shared/conflaunchd.sh</string>
<key>ProgramArguments</key>
<array>
<string>~/.conf.launchd</string>
</array>
<key>EnableGlobbing</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
<string>StandardIO</string>
</array>
</dict>
</plist>
One important thing is the RunAtLoad key so that the launch agent is executed at the earliest time possible.
The real work is done in the shell script /Users/Shared/conflaunchd.sh, which reads ~/.conf.launchd and feeds it to launchctl
:
#! /bin/bash
#filename="$1"
filename="$HOME/.conf.launchd"
if [ ! -r "$filename" ]; then
exit
fi
eval $(/usr/libexec/path_helper -s)
while read line; do
# skip lines that only contain whitespace or a comment
if [ ! -n "$line" -o `expr "$line" : '#'` -gt 0 ]; then continue; fi
eval launchctl $line
done <"$filename"
exit 0
Notice the call of path_helper
to get PATH set up right. Finally, ~/.conf.launchd looks like that
setenv PATH ~/Applications:"${PATH}"
setenv TEXINPUTS .:~/Documents/texmf//:
setenv BIBINPUTS .:~/Documents/texmf/bibtex//:
setenv BSTINPUTS .:~/Documents/texmf/bibtex//:
# Locale
setenv LANG en_US.UTF-8
These are launchctl
commands, see its manpage for further information. Works fine for me (I should mention that I'm still a Snow Leopard guy), GUI applications such as texstudio and TeXShop can see my own tex tree. Things that can be improved:
The shell script has a
#filename="$1"
in it. This is not accidental, as the file name should be feeded to the script by the launch agent as an argument, but that doesn't work.As mentioned here (German and behind a paywall!), it is possible to put the script in the launch agent itsself.
I am not sure how secure this solution is, as it uses
eval
with user provided strings.I think to remember that the definition of MANPATH using this method didn't work well, but I'm not sure.
It should be mentioned that Apple intended a somewhat similar approach by putting stuff in ∼/launchd.conf, but it is currently unsupported as to this date and OS (see the manpage of launchd.conf
). I guess that things like globbing would not work as they do in this proposal. And of course one can put these files anywhere else, except the launch agent which must reside in /Library/LaunchAgents/ or ~/Library/LaunchAgents/.
Finally, I should mention the sources I used as information on Launch Agents: 1, 2, 3, 4.
Update: This does not work in version 10.8 at the moment. Workarounds on a per application basis are described here and here.
Solution 3:
The answer provided by @flori works for me on Maverick provided I run the following commands in Terminal after changing the plist file
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user
killall Finder