Setarea variabilelor de mediu prin launchd.conf nu mai funcționează în OS X Yosemite/El Capitan/macOS Sierra/Mojave? (Programare, Variabile De Mediu, Osx Yosemite, Osx Elcapitan)

Tosh a intrebat.

Se pare că launchd.conf nu-mi mai încarcă variabila de mediu.A mai observat cineva acest lucru?

Există o altă soluție pentru a seta permanent variabilele de mediu?

9 răspunsuri
MortimerGoro

Creați un environment.plist fișier în ~/Library/LaunchAgents/ cu acest conținut:

<?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>

Puteți adăuga mai multe launchctl comenzi în interiorul fișierului <string></string> bloc.

Adresa plist se va activa după repornirea sistemului. De asemenea, puteți utiliza launchctl load ~/Library/LaunchAgents/environment.plist pentru a o lansa imediat.

[Editare]

Aceeași soluție funcționează și în El Capitan.

Xcode 7.0+ nu evaluează în mod implicit variabilele de mediu. Vechiul comportament poate fi activat cu această comandă:

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

[Editare]

Există câteva situații în care acest lucru nu prea funcționează. Dacă computerul este repornit și este selectată opțiunea „Reopen windows when logging back in” (Redeschideți ferestrele când vă conectați din nou), este posibil ca ferestrele redeschise să nu vadă variabilele (Poate că acestea sunt deschise înainte de rularea agentului). De asemenea, dacă vă conectați prin ssh, variabilele nu vor fi setate (deci va trebui să le setați în ~/.bash_profile). În cele din urmă, acest lucru nu pare să funcționeze pentru PATH pe El Capitan și Sierra. Acesta trebuie să fie setat prin „launchctl config user path …” și în /etc/paths.

Comentarii

    21

  • Nu este nevoie să reporniți! Puteți face „launchctl start environment.plist” și să reporniți aplicația de care aveți nevoie pentru a obține noile vars env 😉 –  > Por hasvn.
  • Acest lucru nu ar funcționa cu variabila PATH pentru mine. Așa că, în plus față de această abordare pentru setarea altor variabile, am setat variabila PATH în profilul meu ~/.bash_profile. Este foarte posibil ca acest lucru să nu funcționeze pentru toate cazurile, dar până acum nu am avut nicio problemă. –  > Por djule5.
  • Mi-am dat seama: Pentru a funcționa fără repornire, ar trebui să fie „launchctl load environment.plist”, nu start –  > Por Dave Hartnoll.
  • Ah, da. Nimic nu seamănă cu o setare de configurare obscură care apare de exact 9 ori în tot internetul (google UseSanitizedBuildSystemEnvironment). –  > Por Ohad Schneider.
  • Funcționează și pe Sierra –  > Por Shwouchk.
ruario

[Răspuns original]: Puteți utiliza în continuare launchctl setenv variablename value pentru a seta o variabilă astfel încât să fie preluată de către toate aplicații (aplicații grafice pornite prin Dock sau Spotlight, pe lângă cele pornite prin terminal).

Evident, nu veți dori să faceți acest lucru de fiecare dată când vă conectați.

[Editați]: Pentru a evita acest lucru, lansați AppleScript Editor, introduceți o comandă ca aceasta:

do shell script "launchctl setenv variablename value"

(Utilizați mai multe linii dacă doriți să setați mai multe variabile)

Acum salvați (+s) ca Format fișier: Aplicație. În cele din urmă deschideți System SettingsUtilizatori & GrupuriElemente de autentificare și adăugați noua dvs. aplicație.

[Răspuns original]: Pentru a rezolva această problemă, plasați toate variabilele pe care doriți să le definiți într-un scurt script shell, apoi consultați acest răspuns anterior despre cum să executați un script pe MacOS login. În acest fel, scriptul va fi invocat atunci când utilizatorul se conectează.

[Editați]: Niciuna dintre cele două soluții nu este perfectă, deoarece variabilele vor fi setate doar pentru acel anume utilizator, dar sper/închipui că poate fi tot ce aveți nevoie.

Dacă aveți mai mulți utilizatori, ați putea fie să setați manual un Element de autentificare pentru fiecare dintre ei sau să plasați o copie a fișierului com.user.loginscript.plist în fiecare dintre ei la nivel local Library/LaunchAgents locale, care indică același script de shell.

De acord, niciuna dintre aceste soluții nu este la fel de convenabilă ca /etc/launchd.conf.

[Editare suplimentară]: Un utilizator de mai jos menționează că acest lucru nu a funcționat pentru el. Cu toate acestea, am testat pe mai multe mașini Yosemite și funcționează pentru mine. Dacă aveți o problemă, nu uitați că va trebui să reporniți aplicațiile pentru ca acest lucru să aibă efect. În plus, dacă setați variabilele în terminal prin ~/.profile sau ~/.bash_profile, acestea vor anula lucrurile setate prin launchctl setenv pentru aplicațiile pornite din shell.

Comentarii

  • Din câte îmi dau seama, un dezavantaj al acestei tehnici este că variabila (variabilele) nu va (vor) fi setată (setate) pentru alte aplicații pornite la autentificare. Astfel, de exemplu, dacă deschideți Terminal, variabila va fi setată, dar dacă vă deconectați și vă conectați din nou, Terminal fiind repornit automat, variabila va fi dezactivată… –  > Por JasonD.
  • Am încercat această soluție și nici la mine nu a funcționat. Dar mă aștept în mod special ca IDE-ul meu Java (IntelliJ) să preia modificările de cale și nu o face. Totul funcționează foarte bine din terminal. S-ar putea să fie o eroare în IntelliJ. Totuși, este frustrant că Apple a eliminat această funcționalitate. Am sunat la Apple și nu au fost de mare ajutor. –  > Por Jason.
  • Acest lucru funcționează pentru mine, dar știți ce trebuie să faceți pentru a adăuga și variabilele de mediu la sudo ? –  > Por etiennenoel.
  • Acest lucru va funcționa în general, însă există o eroare în Yosemite (cel puțin în 10.10.0 și 10.10.1) în care setarea lui $PATH nu funcționează în acest mod. Apple este conștientă de acest bug. În prezent (începând cu versiunea 10.10.1), nu există nicio modalitate cunoscută de a seta un $PATH la nivel de sistem pentru aplicațiile GUI. –  > Por TJ Luoma.
  • După ce ați folosit una dintre metodele menționate mai sus și ați repornit laptopul – Asigurați-vă că redeschideți în mod explicit aplicațiile (cum ar fi iTerm, terminal, Eclipse, IDEA sau orice altceva utilizați). Dacă nu le reporniți în mod explicit și Dacă la repornirea OSx a fost bifată caseta de selectare „Restart windows when logging back in” (care este cea implicită) – aceste programe nu vor citi variabilele de mediu proaspete. –  > Por Ați rulat.
ursa

Este posibil să setați variabilele de mediu pe Mac OS X 10.10 Yosemite cu 3 fișiere + 2 comenzi.

Fișierul principal cu definirea variabilelor de mediu:

$ 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"

Definiția serviciului pentru a încărca variabilele de mediu pentru aplicațiile utilizatorului (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>

Aceeași definiție de serviciu pentru aplicațiile utilizatorului root:

$ 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>

Și în final ar trebui să înregistrăm aceste servicii:

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

Ce obținem:

  1. Singurul loc în care se pot declara variabilele de mediu ale sistemului: /etc/environment
  2. Actualizare automată instantanee a variabilelor de mediu după modificarea fișierului /etc/environment – trebuie doar să relansați aplicația dvs.

Aspecte / probleme:

În ordinea în care variabilele de mediu au fost preluate corect de către aplicații după repornirea sistemului veți avea nevoie de:

  • fie să vă autentificați de două ori: login => logout => login
  • fie închideți & redeschideți manual aplicațiile, unde ar trebui să fie preluate variabilele de mediu.
  • fie să NU folosiți funcția „Redeschideți ferestrele la revenirea la logare”.

Acest lucru se întâmplă din cauza faptului că Apple refuză ordonarea explicită a serviciilor încărcate, astfel încât variabilele env sunt înregistrate în paralel cu procesarea „cozii de redeschidere”.

Dar, de fapt, îmi repornesc sistemul doar de câteva ori pe an (la actualizări mari), așa că nu este o mare problemă.

Comentarii

  • O idee excelentă. Am încercat-o și funcționează pentru majoritatea variabilelor de mediu (cum ar fi JAVA_HOME), dar nu și pentru PATH variabilă (vezi întrebarea mea de pe ask different). –  > Por halloleo.
  • PATH ar trebui să fie setat cu fișierul /etc/paths. Adăugați doar calea dvs. personalizată la sfârșitul acestui fișier. –  > Por ursa.
  • Nu sunt atât de familiarizat cu launchd, dar nu ar fi posibil să se încarce aceste Daemons la boot (adică înainte de logare)? Asta ar trebui să ocolească toate problemele pe care le menționați. –  > Por Egon.
  • Îmi place abordarea de mai sus, dar am o problemă ciudată de gestionat. După repornire, un genet VARNAME îmi returnează valoarea corectă, dar echo $VARNAME nu returnează nimic. Care ar putea fi un motiv pentru acest lucru? Am postat asta și pe stackoverflow.com/questions/27045137/…. și sper că cineva de aici are o idee –  > Por ctp.
  • Asigurați-vă că permisiunile fișierului /etc/environment sunt cele descrise mai sus. –  > Por imanuelcostigan.
aax

Citat din

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

După multe deliberări, ingineria a eliminat această caracteristică. Fișierul /etc/launchd.conf a fost eliminat în mod intenționat din motive de securitate. Ca o soluție alternativă, puteți rula launchctl limit ca root la începutul procesului de pornire, poate de la un fișier LaunchDaemon. (…)

Soluție:

Introduceți un cod în /Library/LaunchDaemons/com.apple.launchd.limit.plist de către bash-script:

#!/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

user719662

Comentarii

  • Poți să explici puțin mai mult? Nu văd ce legătură are „Rezolvă problema” cu problema inițială! –  > Por Nick H247.
  • Nu este OP, dar cred că esența aici este: puneți acest plist în /Library/LaunchDaemonsși, în loc de a spune launchctl să ruleze programul limit comanda, spuneți-i să execute comanda setenv comanda cu PATH și un șir de căi ca argumente. launchd ar trebui să o preia automat la pornire și să se auto-modifice aproape imediat. –  > Por Laird Nelson.
  • xml este copiat incomplet. Linia doctype ar trebui să fie <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> –  > Por UloPe.
  • @aax ce parte din acel plist setează de fapt o variabilă de mediu? –  > Por HairOfTheDog.
yanchenko

Iată comenzile pentru a restabili vechiul comportament:

# 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

Acum puteți specifica comenzi precum setenv JAVA_HOME /Library/Java/Home în /etc/launchd.conf.

Verificat pe El Capitan.

Baptiste

Ceea ce a funcționat pentru mine (inspirat din mulțumirile lui aax) :

Lipiți acest lucru în /Library/LaunchDaemons/com.apple.launchd.limit.plist apoi reporniți :

<?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>

Dacă aveți nevoie de ea pas cu pas :

  • Lansați terminalul
  • Tastați sudo su apoi introduceți parola pentru a vă autentifica ca root
  • Tastați vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
  • Când sunteți în editorul vi, apăsați tasta i pentru a intra în modul insert, apoi lipiți exact conținutul de cod de mai sus (⌘+v). Acest lucru va forța limita la 16384 fișiere pe proces și 16384 fișiere în total
  • Salvați fișierul și ieșiți folosind esc apoi :wq
  • Reporniți sistemul și verificați dacă funcționează folosind comanda launchctl limit

Sper că acest lucru v-a ajutat.

Comentarii

  • Ce legătură are această soluție cu setarea variabilelor de mediu? –  > Por HairOfTheDog.
Ersin Er

Puteți da https://github.com/ersiner/osx-env-sync o încercare. Acesta se ocupă de atât linia de comandă, cât și aplicațiile GUI de la un sursă unică și funcționează cu cea mai recentă versiune de OS X (Yosemite).

Puteți folosi substituții de căi și alte trucuri de shell, deoarece ceea ce scrieți este un script bash obișnuit care trebuie să fie preluat de bash în primul rând. Nu există restricții… (Verificați osx-env-sync și veți înțelege cum se realizează acest lucru).

Am răspuns la o întrebare similară aici, unde veți găsi mai multe.

Ilias

Soluția este să adăugați variabila dvs. la /etc/profile. Apoi totul funcționează conform așteptărilor!Desigur, TREBUIE să o faceți ca utilizator root cu sudo nano /etc/profile. Dacă îl editați în orice alt mod, sistemul se va plânge că /etc/profile este deteriorat, chiar dacă schimbați permisiunile la root.

Comentarii

  • Adăugarea variabilelor de mediu în profil este foarte inferioară, deoarece afectează doar procesele shell. –  > Por UloPe.
Robin

Am adăugat variabilele în ~/.bash_profile în felul următor. După ce ați terminat restart/log out și autentificați-vă

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

NOTĂ: fără restart/log out și log in puteți aplica aceste modificări folosind;

source ~/.bash_profile

Comentarii

  • Rețineți că nu trebuie să vă deconectați și să vă conectați din nou. Folosiți doar comanda source, adică source .bash_profile. –  > Por Michael.
  • De asemenea, problema cu această metodă este că tot trebuie să deschideți un terminal înainte ca variabilele de mediu să fie disponibile. Mai bine să faceți ceea ce este în primul răspuns, astfel încât acestea să fie disponibile fără a fi nevoie să deschideți un terminal. –  > Por Michael.
  • Acest lucru nu funcționează pe aplicațiile încărcate prin SpotLight. stackoverflow.com/questions/135688/… –  > Por Rasika Perera.
  • Utilizarea fișierelor de configurare bash este de ajutor limitat, deoarece presupune că ați avut întotdeauna bash ca strămoș al procesului al cărui mediu încercați să îl afectați. Spotlight, finder, emacs, xcode, cronjobs, agenți launchd, orice IDE, browsere de control al sursei, etc. etc. etc., toate acestea nu vor avea bash ca strămoș. Singurul proces care poate cuprinde aceste procese în mod constant este launchd. –  > Por Ben Hyde.