Warum kann ich in OSX Yosemite viele Umgebungsvariablen für GUI-Apps festlegen, aber nicht die spezifische Variable PATH

Nachdem ich die PATH-Probleme von OSX bis zum Mavericks-Release aussortiert hatte, kommen die Probleme in Yosemite zurück!!!

Daher möchte ich die alte launch.confFunktion in der neuen Version von Mac OSX 10.10 Yosemite nachahmen, um die PATH-Umgebungsvariable in GUI-Apps wie Carbon Emacs oder RStudio verfügbar zu haben. Ich habe die großartige Idee von stackoverflow user ursa genutzt , um ein Shell-Skript einzurichten, das Umgebungsvariablen über konfiguriert launchctl. (Siehe seine Stackoverflow-Antwort hier .) Dies funktioniert für die meisten Umgebungsvariablen, aber nicht für die PATH-Variable .

1. Was habe ich getan?

Zuerst schrieb ich das /etc/environment.rcSkript, das so aussah:

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"

Dann habe ich die Plists für erstellt launchd(Auflistungen dieser und anderer erwähnter Skripte im Anhang unten). Dann habe ich sie mit aktiviert

$ sudo launchctrl load ...

Dann habe ich das path_helperDienstprogramm im Shell-Init-Dateiprofil deaktiviert, damit es die Einstellungen /etc/nicht überschreibt . environment.rcUnd schließlich habe ich die Maschine neu gestartet.

2. Was ist der Effekt?

Wenn ich Terminal starte, werden die neuen Umgebungsvariablen JAVA_HOMEund ENVIRONMENT_RCgemäß gesetzt environment.rc, aber PATH ist auf gesetzt

/usr/bin:/bin

Um sicherzustellen, dass keine bashInit-Datei im Weg ist, habe ich stattdessen ein kleines Python-Skript geschrieben (ebenfalls im Anhang), um die Variablen in der aktuellen Umgebung anzuzeigen, und ich führe dies direkt durch Doppelklicken auf einen Platypus - Wrapper aus. Wieder werden die neuen Variablen gesetzt, während PATH die Systemvorgabe hat.

Warum kann ich also andere Variablen setzen, aber nicht die PATH-Variable? Und wie kann ich das einheitlich lösen ?

Aktualisieren:

Die Situation ist sehr verwirrend: Die Shell ( bashzumindest) in Terminal oder Emacs wird den PATH aufnehmen, den Sie über eingestellt launchctlhaben, aber andere GUI-Apps werden dies nicht tun. Beispielsweise wird das erwähnte minimale Python-Skript, das direkt über Platypus aufgerufen wird, Ihre Gewohnheit nicht anzeigen Weg. Und auch Emacs selbst kennt den richtigen PATH nicht: Das merkt man zB, wenn man den Emacs-Befehl absetzt M-x ispell-buffer; Das Unix-Tool ispell, das Emacs aufzurufen versucht, wird nicht gefunden, wenn es sich nur in Ihrem benutzerdefinierten Pfad befindet.


Anhang

net.halloleo.environment.plist, die launchd-Konfigurationsdatei 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, die launchd-Konfigurationsdatei 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, die modifizierte Bash-Startdatei:

# 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, das Skript, das alle Umgebungsvariablen anzeigt:

import os
print (os.environ)

Antworten (3)

PATH in Yosemite kann und sollte in der Datei /etc/paths gesetzt werden. Fügen Sie einfach Ihren Pfad am Ende dieser Datei hinzu:

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

Das /etc/environment-Skript im ursprünglichen Beitrag bietet Unterstützung für die PATH-Variable in GUI-Anwendungen (getestet mit Emacs).

Dies funktioniert nur für Shells, die /usr/libexec/path_helperwährend ihres Initialisierungsprozesses aufrufen. GUI-Apps erhalten den PATH nicht entsprechend /etc/paths- und ich habe speziell nach GUI-Apps gefragt.
Ich habe die Antwort und das /etc/environment-Skript im ursprünglichen Beitrag aktualisiert
Dies sind zwei Antworten, die Sie geben - auch das OP sagt, /etc/environment funktioniert nicht
@mark (1) nachdem diese Frage gestellt wurde, habe ich /etc/environment aktualisiert und jetzt unterstützt es PATH. (2) Die Antwort hier ist, /etc/paths zu verwenden
Entschuldigung, ursa, für mich, auch wenn ich /etc/environmentanstelle von /etc/environment.rc(als Dateiname und in den plists referenziert) verwende, ist der PATH in der Umgebung der gestarteten GUI immer noch /usr/bin:/bin. Überprüfen Sie in Carbon Emacs, das per Doppelklick im Finder (!) und ohne .emacsDatei gestartet wurde, den Wert von exec-pathoder process-environment.
Ok. Versuchen Sie es in Schritten: (1) Rufen Sie im Terminal "launchctl setenv PATH /your/custom/path:/bin:/usr/bin" auf (2) starten Sie die Dock-Anwendung neu "osascript -e 'tell app "Dock" to quit'" ( 3) Starten Sie Emacs mit dem Spotlight-Menü (4) > Tools > Shell-Befehl > echo $PATH. was druckt es?
Hat für mich funktioniert. sudo vim /etc/pathsdann neustarten und hat super geklappt. Vielen Dank.
@ursa Entschuldigung für meine späte Antwort. Wenn ich die vier von Ihnen vorgeschlagenen Schritte ausführe, erhalte ich das von Ihnen erwähnte Ergebnis, aber das bedeutet nicht, dass PATH in der Emacs-Umgebung richtig eingestellt ist, es zeigt nur, dass die von gestartete Shell shell-commandden richtigen PATH erhält. Es ist eine sehr verwirrende Situation. Ich werde die Frage mit diesen Details aktualisieren.
@halloleo das würde ich erwarten - der Shell-Befehl in Emacs startet eine neue Shell und diese Shell liest /etc/path und .bashrc usw., aber Emacs selbst wird nicht über den Shell-Mechanismus aufgerufen
@mark Ja, und das ist genau mein Punkt, Problem und meine Frage: Wie kann ich die Umgebungsvariable PATH von GUI-Apps selbst festlegen, wenn sie über den Finder gestartet werden? Eine wirkliche generelle Lösung dafür ist aber noch nicht in Sicht...

Das hat mich lange verwirrt (naja, die letzten paar Stunden). Am Ende stieß ich auf diesen Fehlerbericht, der mein Problem genau zu beschreiben scheint (ich bin mir nicht sicher, inwieweit er mit Ihrem Problem zusammenhängt, aber es scheint einen Fehler in Yosemite/launchd in Kombination mit PATH und Skripten wie z als Python:

http://www.openradar.me/18945659

Die Lösung scheint darin zu bestehen, ein Shell-Skript zu starten, das dann den Python startet. Nicht wirklich was ich mag, aber es ist so wie es ist....

Danke für den Link zum Fehlerbericht. Gut, dass es sich jetzt um einen echten Bug handelt. Ich fand eine andere Kupplung darum herum; Ich werde es hier posten.

Das Problem ist, dass launchd eine andere PATH-Variable anhängt, anstatt die in der Umgebung zu ersetzen. Die meisten Programme verwenden getenv, die immer das erste Vorkommen einer Variablen zurückgeben, Shells durchlaufen stattdessen alle Umgebungsvariablen und importieren sie als lokale Variablen, wodurch vorherige Instanzen mit der letzten überschrieben werden.

Dies ist offensichtlich ein Fehler in launchd, Umgebungsvariablen, die an ein Programm übergeben werden, sollten eindeutig sein.

Coole Hintergrundantwort! Ich denke, in Muscheln gibt es keinen wirklichen Weg, oder gibt es?
@halloleo Sie können den Befehl starten, der sh -c 'YOUR ORIGINAL COMMAND'ihn durch die Shell führt, indem Sie den PATHSatz in launchd auswählen.