Das Festlegen von Umgebungsvariablen über launchd.conf funktioniert unter OS X nicht mehr. Yosemite / El Capitan / macOS Sierra / Mojave?

189

Es sieht so aus, als würde die launchd.confUmgebungsvariable nicht mehr geladen. Hat das noch jemand bemerkt?

Gibt es eine andere Lösung, um Umgebungsvariablen dauerhaft festzulegen?

Tosh
quelle
Es funktioniert und stellt sich in der Anwendung zur Verfügung, aber nicht im Terminal
Chang Zhao

Antworten:

158

Erstellen Sie eine environment.plistDatei ~/Library/LaunchAgents/mit diesem Inhalt:

<?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>my.startup</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>
    launchctl setenv PRODUCTS_PATH /Users/mortimer/Projects/my_products
    launchctl setenv ANDROID_NDK_HOME /Applications/android-ndk
    launchctl setenv PATH $PATH:/Applications/gradle/bin
    </string>

  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Sie können launchctldem <string></string>Block viele Befehle hinzufügen .

Das plistwird nach dem Neustart des Systems aktiviert. Sie können es auch verwenden launchctl load ~/Library/LaunchAgents/environment.plist, um es sofort zu starten.

[Bearbeiten]

Die gleiche Lösung funktioniert auch in El Capitan.

Xcode 7.0+ wertet Umgebungsvariablen standardmäßig nicht aus. Das alte Verhalten kann mit diesem Befehl aktiviert werden:

defaults write com.apple.dt.Xcode UseSanitizedBuildSystemEnvironment -bool NO

[Bearbeiten]

Es gibt einige Situationen, in denen dies nicht ganz funktioniert. Wenn der Computer neu gestartet wird und "Fenster beim erneuten Anmelden erneut öffnen" ausgewählt ist, werden die Variablen in den erneut geöffneten Fenstern möglicherweise nicht angezeigt (möglicherweise werden sie geöffnet, bevor der Agent ausgeführt wird). Wenn Sie sich über ssh anmelden, werden die Variablen nicht festgelegt (Sie müssen sie daher in ~ / .bash_profile festlegen). Schließlich scheint dies für PATH auf El Capitan und Sierra nicht zu funktionieren. Dies muss über 'launchctl config user path ...' und in / etc / path eingestellt werden.

MortimerGoro
quelle
20
Kein Neustart erforderlich! Sie können "launchctl start environment.plist" ausführen und die App neu starten, die Sie benötigen, um die neuen env vars zu erhalten;)
hasvn
1
Dies würde mit der PATH-Variablen für mich nicht funktionieren. Zusätzlich zu diesem Ansatz zum Festlegen anderer Variablen habe ich die PATH-Variable in meinem ~ / .bash_profile festgelegt. Das funktioniert vielleicht nicht in jedem Fall, aber bisher habe ich kein Problem.
djule5
6
Ich habe es herausgefunden: Um ohne Neustart zu arbeiten, sollte es "launchctl load environment.plist" sein, nicht start
Dave Hartnoll
2
Ah ja. Nichts wie eine obskure Konfigurationseinstellung, die im gesamten Internet (Google UseSanitizedBuildSystemEnvironment) genau neunmal angezeigt wird .
Ohad Schneider
2
Funktioniert auch in Sierra
Shwouchk
64

[ Ursprüngliche Antwort ]: Sie können weiterhin launchctl setenv variablename valueeine Variable festlegen, die von allen Anwendungen erfasst wird (grafische Anwendungen, die über das Dock oder Spotlight gestartet wurden, zusätzlich zu denen, die über das Terminal gestartet wurden).

Natürlich möchten Sie dies nicht jedes Mal tun, wenn Sie sich anmelden.

[ Bearbeiten ]: Um dies zu vermeiden, starten Sie AppleScript Editorund geben Sie einen Befehl wie den folgenden ein:

do shell script "launchctl setenv variablename value"

(Verwenden Sie mehrere Zeilen, wenn Sie mehrere Variablen festlegen möchten.)

Speichern Sie nun ( + s) als Dateiformat: Anwendung . Öffnen Sie abschließendSystem SettingsBenutzer & GruppenAnmeldeelemente und fügen Sie Ihre neue Anwendung hinzu.

[ Ursprüngliche Antwort ]: Um diesen Ort zu umgehen, platzieren Sie alle Variablen, die Sie in einem kurzen Shell-Skript definieren möchten. Schauen Sie sich dann diese vorherige Antwort an, wie Sie ein Skript unter MacOS-Login ausführen . Auf diese Weise wird das Skript aufgerufen, wenn sich der Benutzer anmeldet.

[ Bearbeiten ]: Keine der beiden Lösungen ist perfekt, da die Variablen nur für diesen bestimmten Benutzer festgelegt werden, aber ich hoffe / vermute, dass dies alles ist, was Sie benötigen.

Wenn Sie mehrere Benutzer haben, können Sie entweder manuell ein Anmeldeelement für jeden von ihnen festlegen oder eine Kopie von com.user.loginscript.plist in jeder ihrer lokalen Bibliotheken / LaunchAgents ablegen Verzeichnisse und auf dasselbe Shell-Skript verweisen.

Zugegeben, keine dieser Problemumgehungen ist so praktisch wie /etc/launchd.conf .

[ Weitere Bearbeitung ]: Ein Benutzer unten erwähnt, dass dies bei ihm nicht funktioniert hat. Ich habe jedoch auf mehreren Yosemite-Computern getestet und es funktioniert für mich. Wenn Sie ein Problem haben, denken Sie daran, dass Sie Anwendungen neu starten müssen, damit dies wirksam wird. Wenn Sie Variablen im Terminal über ~ / .profile oder ~ / .bash_profile festlegen , überschreiben sie außerdem die über launchctl setenv festgelegten Elemente für Anwendungen, die über die Shell gestartet wurden .

Ruario
quelle
5
Soweit ich das beurteilen kann, besteht ein Nachteil dieser Technik darin, dass die Variablen nicht für andere Anwendungen festgelegt werden, die beim Anmelden gestartet wurden. Wenn Sie beispielsweise Terminal öffnen, wird die Variable festgelegt. Wenn Sie sich jedoch abmelden und wieder anmelden und der Terminal automatisch neu
gestartet
Ich habe diese Lösung ausprobiert und sie hat auch bei mir nicht funktioniert. Ich erwarte jedoch ausdrücklich, dass meine Java-IDE (IntelliJ) meine Pfadänderungen übernimmt, und dies ist nicht der Fall. Vom Terminal aus funktioniert alles einwandfrei. Es könnte ein Fehler in IntelliJ sein. Immer noch frustrierend, dass Apple diese Funktionalität entfernt hat. Ich habe Apple angerufen und sie waren nicht sehr hilfreich.
Jason
Das funktioniert bei mir, aber wissen Sie, was Sie tun müssen, um auch die Umgebungsvariablen zu sudo hinzuzufügen?
Etiennenoel
2
Dies funktioniert im Allgemeinen, es gibt jedoch einen Fehler in Yosemite (mindestens 10.10.0 und 10.10.1), bei dem das Festlegen von $ PATH nicht auf diese Weise funktioniert. Apple ist sich des Fehlers bewusst. Derzeit (Stand 10.10.1) ist keine Möglichkeit bekannt, einen systemweiten $ PATH für GUI-Apps festzulegen.
TJ Luoma
3
Nachdem Sie eine der oben genannten Methoden verwendet und Ihren Laptop neu gestartet haben - Stellen Sie sicher, dass Sie die Anwendungen explizit neu öffnen (z. B. iTerm, Terminal, Eclipse, IDEA oder was auch immer Sie verwenden). Wenn Sie sie nicht explizit neu starten und wenn beim Neustart von OSx das Kontrollkästchen "Fenster beim erneuten Anmelden neu starten" aktiviert wurde (dies ist die Standardeinstellung), lesen diese Programme die neuen Umgebungsvariablen nicht.
Ran
21

Unter Mac OS X 10.10 Yosemite können Umgebungsvariablen mit 3 Dateien + 2 Befehlen festgelegt werden.

Hauptdatei mit Definition der Umgebungsvariablen:

$ ls -la /etc/environment 
-r-xr-xr-x  1 root  wheel  369 Oct 21 04:42 /etc/environment
$ cat /etc/environment
#!/bin/sh

set -e

syslog -s -l warn "Set environment variables with /etc/environment $(whoami) - start"

launchctl setenv JAVA_HOME      /usr/local/jdk1.7
launchctl setenv MAVEN_HOME     /opt/local/share/java/maven3

if [ -x /usr/libexec/path_helper ]; then
    export PATH=""
    eval `/usr/libexec/path_helper -s`
    launchctl setenv PATH $PATH
fi

osascript -e 'tell app "Dock" to quit'

syslog -s -l warn "Set environment variables with /etc/environment $(whoami) - complete"

Dienstdefinition zum Laden von Umgebungsvariablen für Benutzeranwendungen (Terminal, IDE, ...):

$ ls -la /Library/LaunchAgents/environment.user.plist
-rw-------  1 root  wheel  504 Oct 21 04:37 /Library/LaunchAgents/environment.user.plist
$ sudo cat /Library/LaunchAgents/environment.user.plist
<?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>environment.user</string>
    <key>ProgramArguments</key>
    <array>
            <string>/etc/environment</string>
    </array>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/etc/environment</string>
    </array>
</dict>
</plist>

Dieselbe Dienstdefinition für Root-Benutzeranwendungen:

$ ls -la /Library/LaunchDaemons/environment.plist
-rw-------  1 root  wheel  499 Oct 21 04:38 /Library/LaunchDaemons/environment.plist
$ sudo cat /Library/LaunchDaemons/environment.plist
<?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>environment</string>
    <key>ProgramArguments</key>
    <array>
            <string>/etc/environment</string>
    </array>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/etc/environment</string>
    </array>
</dict>
</plist>

Und schließlich sollten wir diese Dienste registrieren:

$ launchctl load -w /Library/LaunchAgents/environment.user.plist
$ sudo launchctl load -w /Library/LaunchDaemons/environment.plist

Was wir bekommen:

  1. Der einzige Ort, an dem Systemumgebungsvariablen deklariert werden können: / etc / environment
  2. Sofortige automatische Aktualisierung von Umgebungsvariablen nach Änderung der Datei / etc / environment - Starten Sie einfach Ihre Anwendung neu

Probleme / Probleme:

Damit Ihre env-Variablen nach dem Neustart des Systems von den Anwendungen korrekt übernommen wurden, benötigen Sie:

  • entweder zweimal anmelden: login => logout => login
  • oder Anwendungen manuell schließen und erneut öffnen, wobei env-Variablen verwendet werden sollten
  • oder verwenden Sie NICHT die Funktion "Fenster beim Zurückmelden erneut öffnen".

Dies liegt daran, dass Apple die explizite Bestellung geladener Dienste verweigert, sodass env-Variablen parallel zur Verarbeitung der "Wiedereröffnungswarteschlange" registriert werden.

Tatsächlich starte ich mein System jedoch nur mehrmals pro Jahr neu (bei großen Updates), es ist also keine große Sache.

ursa
quelle
Großartige Idee. Ich habe es versucht und es funktioniert für die meisten Umgebungsvariablen (wie JAVA_HOME), aber nicht für die PATHVariable (siehe meine Frage auf anders stellen ).
Halloleo
4
PATH sollte mit der Datei / etc / path festgelegt werden. Fügen Sie einfach Ihren benutzerdefinierten Pfad am Ende dieser Datei hinzu.
Ursa
Ich bin nicht so vertraut damit launchd, aber wäre es nicht möglich, diese Daemons beim Booten (dh vor dem Anmelden) zu laden? Das sollte alle von Ihnen erwähnten Probleme umgehen.
Egon
Ich liebe den obigen Ansatz, habe aber ein seltsames Problem zu bewältigen. Nach dem Neustart gibt mir ein genetischer VARNAME den richtigen Wert zurück, aber echo $ VARNAME gibt nichts zurück. Was könnte ein Grund dafür sein? Ich habe das auch auf stackoverflow.com/questions/27045137/… gepostet und hoffe, dass hier jemand eine Idee hat
ctp
Stellen Sie sicher, dass die Dateiberechtigungen von / etc / environment wie oben beschrieben sind.
Imanuelcostigan
6

Zitiert von

Apple Developer Relations 10-Oct-2014 09:12 PM

Nach langem Überlegen hat das Engineering diese Funktion entfernt. Die Datei /etc/launchd.confwurde aus Sicherheitsgründen absichtlich entfernt. Um dieses Problem zu umgehen, können Sie launchctl limitfrüh während des Startvorgangs als Root ausgeführt werden, möglicherweise von a LaunchDaemon. (...)

Lösung:

Fügen Sie Code /Library/LaunchDaemons/com.apple.launchd.limit.plistper Bash-Skript ein:

#!/bin/bash

echo '<?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>eicar</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/launchctl</string>
                <string>limit</string>
                <string>core</string>
                <string>unlimited</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>ServiceIPC</key>
        <false/>
</dict>
</plist>' | sudo tee /Library/LaunchDaemons/com.apple.launchd.limit.plist
aax
quelle
1
Können Sie das etwas näher erläutern? Ich kann nicht sehen, wie sich das Problem "Lösen" auf das ursprüngliche Problem bezieht!
Nick H247
Nicht das OP, aber ich denke, das Wesentliche hier ist: Setzen Sie diese Liste ein /Library/LaunchDaemons, und anstatt zu sagen launchctl, dass der limitBefehl ausgeführt werden soll, weisen Sie ihn an, den setenvBefehl mit PATHund einer Pfadzeichenfolge als Argumente auszuführen . launchdsollte es beim Start automatisch abholen und sich fast sofort selbst modifizieren.
Laird Nelson
5
Die XML wird unvollständig kopiert. Die Doctype-Zeile sollte lauten<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
UloPe
6
@aax Welcher Teil dieser Liste setzt tatsächlich eine Umgebungsvariable?
HairOfTheDog
3

Hier sind die Befehle zum Wiederherstellen des alten Verhaltens:

# create a script that calls launchctl iterating through /etc/launchd.conf
echo '#!/bin/sh

while read line || [[ -n $line ]] ; do launchctl $line ; done < /etc/launchd.conf;
' > /usr/local/bin/launchd.conf.sh

# make it executable
chmod +x /usr/local/bin/launchd.conf.sh

# launch the script at startup
echo '<?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>launchd.conf</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>/usr/local/bin/launchd.conf.sh</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>
' > /Library/LaunchAgents/launchd.conf.plist

Jetzt können Sie Befehle wie setenv JAVA_HOME /Library/Java/Homein angeben /etc/launchd.conf.

Auf El Capitan überprüft.

yanchenko
quelle
2

Was hat bei mir funktioniert (inspiriert von Aax 'Dank):

Fügen Sie dies in /Library/LaunchDaemons/com.apple.launchd.limit.plist ein und starten Sie es neu:

<?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>eicar</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/launchctl</string>
    <string>limit</string>
    <string>maxfiles</string>
    <string>16384</string>
    <string>16384</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>ServiceIPC</key>
  <false/>
</dict>
</plist>

Wenn Sie es Schritt für Schritt brauchen:

  • Terminal starten
  • Geben Sie sudo su ein und geben Sie Ihr Passwort ein, um sich als root anzumelden
  • Geben Sie vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
  • Drücken Sie im vi-Editor die Taste i , um den Einfügemodus aufzurufen, und fügen Sie dann den genauen Codeinhalt über ( ⌘+v) ein. Dadurch wird das Limit auf 16384 Dateien pro Prozess und insgesamt 16384 Dateien erzwungen
  • Speichern Sie die Datei und beenden Sie mit escdann:wq
  • Starten Sie Ihr System neu und überprüfen Sie mithilfe des Befehls launchctl limit , ob es funktioniert

Ich hoffe das hat dir geholfen.

Baptiste
quelle
10
Was hat diese Lösung mit dem Setzen von Umgebungsvariablen zu tun?
HairOfTheDog
2

Sie können https://github.com/ersiner/osx-env-sync ausprobieren. Es verarbeitet sowohl Befehlszeilen- als auch GUI-Apps aus einer Hand und funktioniert mit der neuesten Version von OS X (Yosemite).

Sie können Pfadsubstitutionen und andere Shell-Tricks verwenden, da Sie ein reguläres Bash-Skript schreiben, das in erster Linie von Bash bezogen wird. Keine Einschränkungen. (Überprüfen Sie die Dokumentation zu osx-env-sync und Sie werden verstehen, wie dies erreicht wird.)

Ich habe hier eine ähnliche Frage beantwortet , wo Sie mehr finden.

Ersin Er
quelle
-3

Die Lösung besteht darin, Ihre Variable hinzuzufügen /etc/profile. Dann funktioniert alles wie erwartet! Natürlich MÜSSEN Sie dies als Root-Benutzer mit sudo nano / etc / profile tun. Wenn Sie es auf andere Weise bearbeiten, beschwert sich das System mit einem beschädigten / etc / profile, selbst wenn Sie die Berechtigungen in root ändern.

Ilias
quelle
7
Das Hinzufügen von Umgebungsvariablen zum Profil ist sehr viel schlechter, da es nur Shell-Prozesse betrifft.
UloPe
-5

Ich habe die Variablen im ~ / .bash_profile folgendermaßen hinzugefügt. Nachdem Sie fertig sind, starten Sie neu / melden Sie sich ab und melden Sie sich an

export M2_HOME=/Users/robin/softwares/apache-maven-3.2.3
export ANT_HOME=/Users/robin/softwares/apache-ant-1.9.4
launchctl setenv M2_HOME $M2_HOME
launchctl setenv ANT_HOME $ANT_HOME
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/robin/softwares/apache-maven-3.2.3/bin:/Users/robin/softwares/apache-ant-1.9.4/bin
launchctl setenv PATH $PATH

HINWEIS: Ohne Neustart / Abmelden und Anmelden können Sie diese Änderungen mit anwenden.

source ~/.bash_profile
Robin
quelle
Beachten Sie, dass Sie sich nicht ab- und wieder anmelden müssen. Verwenden Sie einfach den Quellbefehl, dh source .bash_profile.
Michael
2
Das Problem bei dieser Methode ist auch, dass Sie noch ein Terminal öffnen müssen, bevor die Umgebungsvariablen verfügbar sind. Tun Sie besser, was in der ersten Antwort steht, damit sie verfügbar sind, ohne ein Terminal öffnen zu müssen.
Michael
1
Dies funktioniert nicht bei Apps, die über SpotLight geladen wurden. stackoverflow.com/questions/135688/…
Rasika Perera
1
Die Verwendung der Bash-Konfigurationsdateien ist nur begrenzt hilfreich, da davon ausgegangen wird, dass Sie Bash immer als Vorfahr des Prozesses haben, dessen Umgebung Sie beeinflussen möchten. Spotlight, der Finder, Emacs, Xcode, Cronjobs, Launchd-Agenten, IDE, Quellcodeverwaltungsbrowser usw. usw. werden keine Bash als Vorfahren haben. Der einzige Prozess, der diese konsistent umfassen kann, ist startd.
Ben Hyde