La définition des variables d'environnement via launchd.conf ne fonctionne plus sous OS X Yosemite / El Capitan / macOS Sierra / Mojave?

190

Il semble que le launchd.confne charge plus ma variable d'environnement. Quelqu'un d'autre a-t-il remarqué cela?

Existe-t-il une autre solution pour définir de manière permanente les variables d'environnement?

Tosh
la source
Cela fonctionne et se rend disponible dans l'application mais pas dans le terminal
Chang Zhao

Réponses:

159

Créez un environment.plistfichier ~/Library/LaunchAgents/avec ce contenu:

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

Vous pouvez ajouter de nombreuses launchctlcommandes à l'intérieur du <string></string>bloc.

L' plistactivera après le redémarrage du système. Vous pouvez également l'utiliser launchctl load ~/Library/LaunchAgents/environment.plistpour le lancer immédiatement.

[Éditer]

La même solution fonctionne également à El Capitan.

Xcode 7.0+ n'évalue pas les variables d'environnement par défaut. L'ancien comportement peut être activé avec cette commande:

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

[Éditer]

Il y a quelques situations où cela ne fonctionne pas tout à fait. Si l'ordinateur est redémarré et que "Rouvrir les fenêtres lors de la reconnexion" est sélectionné, les fenêtres rouvertes risquent de ne pas voir les variables (elles sont peut-être ouvertes avant l'exécution de l'agent). De plus, si vous vous connectez via ssh, les variables ne seront pas définies (vous devrez donc les définir dans ~ / .bash_profile). Enfin, cela ne semble pas fonctionner pour PATH sur El Capitan et Sierra. Cela doit être défini via 'launchctl config user path ...' et dans / etc / chemins.

MortimerGoro
la source
20
Pas besoin de redémarrer! Vous pouvez faire "launchctl start environment.plist" et redémarrer l'application dont vous avez besoin pour obtenir les nouveaux vars env;)
hasvn
1
Cela ne fonctionnerait pas avec la variable PATH pour moi. Donc, en plus de cette approche pour définir d'autres variables, j'ai défini la variable PATH dans mon ~ / .bash_profile. Cela pourrait ne pas fonctionner pour tous les cas, mais jusqu'à présent, je n'ai pas de problème.
djule5
6
Compris: pour fonctionner sans redémarrage, il devrait être "launchctl load environment.plist", pas démarrer
Dave Hartnoll
2
Ah oui. Rien de tel qu'un paramètre de configuration obscur qui apparaît exactement 9 fois sur tout Internet (google UseSanitizedBuildSystemEnvironment).
Ohad Schneider
2
Fonctionne également sur Sierra
Shwouchk
64

[ Réponse originale ]: Vous pouvez toujours utiliser launchctl setenv variablename valuepour définir une variable afin qu'elle soit captée par toutes les applications (applications graphiques démarrées via le Dock ou Spotlight, en plus de celles démarrées via le terminal).

Évidemment, vous ne voudrez pas faire cela à chaque fois que vous vous connectez.

[ Modifier ]: pour éviter cela, lancez AppleScript Editor, entrez une commande comme celle-ci:

do shell script "launchctl setenv variablename value"

(Utilisez plusieurs lignes si vous souhaitez définir plusieurs variables)

Maintenant, enregistrez ( + s) comme Format de fichier: Application . Enfin, ouvrez System SettingsUtilisateurs et groupesÉléments de connexion et ajoutez votre nouvelle application.

[ Réponse originale ]: Pour contourner toutes les variables que vous souhaitez définir dans un court script shell, jetez un œil à cette réponse précédente sur la façon d'exécuter un script sur la connexion MacOS . De cette façon, le script sera appelé lorsque l'utilisateur se connectera.

[ Modifier ]: Aucune des deux solutions n'est parfaite car les variables ne seront définies que pour cet utilisateur spécifique, mais j'espère / devine que cela peut être tout ce dont vous avez besoin.

Si vous avez plusieurs utilisateurs, vous pouvez soit définir manuellement un élément de connexion pour chacun d'eux, soit placer une copie de com.user.loginscript.plist dans chacun de leurs répertoires Library / LaunchAgents locaux , en pointant sur le même script shell.

Certes, aucune de ces solutions de contournement n'est aussi pratique que /etc/launchd.conf .

[ Modification supplémentaire ]: Un utilisateur ci-dessous mentionne que cela n'a pas fonctionné pour lui. Cependant, j'ai testé sur plusieurs machines Yosemite et cela fonctionne pour moi. Si vous rencontrez un problème, n'oubliez pas que vous devrez redémarrer les applications pour que cela prenne effet. De plus, si vous définissez des variables dans le terminal via ~ / .profile ou ~ / .bash_profile , elles remplaceront les éléments définis via launchctl setenv pour les applications démarrées depuis le shell .

ruario
la source
5
Pour autant que je sache, l'un des inconvénients de cette technique est que la ou les variables ne seront pas définies pour les autres applications démarrées lors de la connexion. Ainsi, par exemple, si vous ouvrez Terminal, la variable sera définie, mais si vous vous déconnectez puis vous
reconnectez
J'ai essayé cette solution et cela n'a pas fonctionné pour moi non plus. Mais je m'attends spécifiquement à ce que mon IDE Java (IntelliJ) reprenne les modifications de mon chemin et ce n'est pas le cas. Tout fonctionne très bien depuis le terminal. Cela pourrait être un bogue dans IntelliJ. Toujours frustrant qu'Apple ait supprimé cette fonctionnalité. J'ai appelé Apple et ils n'ont pas été très utiles.
Jason
Cela fonctionne pour moi, mais savez-vous quoi faire pour ajouter également les variables d'environnement à sudo?
etiennenoel
2
Cela fonctionnera en général, mais il y a un bogue dans Yosemite (10.10.0 et 10.10.1 au moins) où la configuration de $ PATH ne fonctionne pas de cette façon. Apple est conscient du bogue. Actuellement (à partir de 10.10.1), il n'existe aucun moyen connu de définir un $ PATH à l'échelle du système pour les applications GUI.
TJ Luoma
3
Après avoir utilisé l'une des méthodes mentionnées ci-dessus et redémarré votre ordinateur portable - Assurez-vous de rouvrir explicitement les applications (telles que iTerm, terminal, Eclipse, IDEA ou tout ce que vous utilisez). Si vous ne les redémarrez pas explicitement et si lors du redémarrage d'OSx, la case à cocher a été cochée sur "Redémarrer les fenêtres lors de la reconnexion" (qui est la valeur par défaut) - ces programmes ne liront pas les nouvelles variables d'environnement.
couru
21

Il est possible de définir des variables d'environnement sur Mac OS X 10.10 Yosemite avec 3 fichiers + 2 commandes.

Fichier principal avec définition des variables d'environnement:

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

Définition de service pour charger des variables d'environnement pour les applications utilisateur (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>

La même définition de service pour les applications utilisateur 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>

Et enfin, nous devrions enregistrer ces services:

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

Ce que nous obtenons:

  1. Le seul endroit pour déclarer les variables d'environnement système: / etc / environment
  2. Mise à jour automatique instantanée des variables d'environnement après modification du fichier / etc / environment - relancez simplement votre application

Problèmes / problèmes:

Pour que vos variables d'environnement soient correctement prises par les applications après le redémarrage du système, vous aurez besoin de:

  • soit connectez-vous deux fois: login => logout => login
  • ou fermez et rouvrez les applications manuellement, où les variables d'environnement doivent être prises
  • ou n'utilisez PAS la fonction «Rouvrir les fenêtres lors de la reconnexion».

Cela se produit parce qu'Apple refuse l'ordre explicite des services chargés, de sorte que les variables env sont enregistrées en parallèle avec le traitement de la "file d'attente de réouverture".

Mais en fait, je ne redémarre mon système que plusieurs fois par an (sur de grosses mises à jour), donc ce n'est pas un gros problème.

Ursa
la source
Bonne idée. Je l'ai essayé et cela fonctionne pour la plupart des variables d'environnement (comme JAVA_HOME), mais pas pour la PATHvariable (voir ma question sur demander différent ).
halloleo
4
PATH doit être défini avec le fichier / etc / chemins. Ajoutez simplement votre chemin personnalisé à la fin de ce fichier.
ursa
Je ne suis pas familier avec launchd, mais ne serait-il pas possible de charger ces démons au démarrage (c'est-à-dire avant la connexion)? Cela devrait contourner tous les problèmes que vous mentionnez.
Egon
J'adore l'approche ci-dessus mais j'ai un problème étrange à gérer. Après le redémarrage, une genet VARNAME me renvoie la bonne valeur mais echo $ VARNAME ne renvoie rien. Quelle pourrait en être la raison? J'ai posté ça sur stackoverflow.com/questions/27045137/ ... aussi et j'espère que quelqu'un ici a une idée
ctp
Assurez-vous que les autorisations de fichier de / etc / environment sont telles que décrites ci-dessus.
imanuelcostigan
6

Cité de

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

Après de longues délibérations, l'ingénierie a supprimé cette fonctionnalité. Le fichier a /etc/launchd.confété supprimé intentionnellement pour des raisons de sécurité. Pour contourner ce problème, vous pouvez exécuterlaunchctl limit tant que root au début du démarrage, peut-être à partir d'un fichier LaunchDaemon. (...)

Solution:

Mettez le code dans /Library/LaunchDaemons/com.apple.launchd.limit.plistpar 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
aax
la source
1
Pouvez-vous expliquer cela un peu plus? Je ne vois pas comment le «problème résolu» est lié au problème initial!
Nick H247 du
Pas l'OP, mais je pense que l'essentiel ici est: mettez ce plist dans /Library/LaunchDaemons, et au lieu de dire launchctld'exécuter la limitcommande, dites-lui d'exécuter la setenvcommande avec PATHet une chaîne de chemin comme arguments. launchddevrait le récupérer automatiquement au démarrage et être en quelque sorte auto-modifié presque immédiatement.
Laird Nelson
5
Le xml n'est pas copié complètement. La ligne doctype devrait se lire<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
UloPe
6
@aax quelle partie de ce plist définit réellement une variable d'environnement?
HairOfTheDog
3

Voici les commandes pour restaurer l'ancien comportement:

# 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

Vous pouvez maintenant spécifier des commandes comme setenv JAVA_HOME /Library/Java/Homedans/etc/launchd.conf .

Vérifié sur El Capitan.

Yanchenko
la source
2

Qu'est-ce qui a fonctionné pour moi (inspiré de merci aax):

Collez-le dans /Library/LaunchDaemons/com.apple.launchd.limit.plist puis redémarrez:

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

Si vous en avez besoin étape par étape:

  • Terminal de lancement
  • Tapez sudo su puis entrez votre mot de passe pour vous connecter en tant que root
  • Tapez vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
  • Une fois dans l'éditeur vi, appuyez sur la touche i pour entrer en mode insertion, puis collez le contenu du code exact ci-dessus (⌘+v ). Cela forcera la limite à 16384 fichiers par processus et 16384 fichiers au total
  • Enregistrez votre fichier et quittez en utilisant escpuis:wq
  • Redémarrez votre système et vérifiez qu'il fonctionne à l'aide de la commande launchctl limit

J'espère que cela vous a aidé.

Baptiste
la source
10
Qu'est-ce que cette solution a à voir avec la définition des variables d'environnement?
HairOfTheDog
2

Vous pouvez essayer https://github.com/ersiner/osx-env-sync . Il gère à la fois les applications de ligne de commande et d'interface graphique à partir d'une seule source et fonctionne avec la dernière version d'OS X (Yosemite).

Vous pouvez utiliser des substitutions de chemin et d'autres astuces de shell puisque ce que vous écrivez est un script bash normal qui doit être obtenu par bash en premier lieu. Aucune restriction. (Consultez la documentation osx-env-sync et vous comprendrez comment il y parvient.)

J'ai répondu à une question similaire ici où vous en trouverez plus.

Ersin Er
la source
-3

La solution consiste à ajouter votre variable à /etc/profile. Ensuite, tout fonctionne comme prévu! Bien sûr, vous DEVEZ le faire en tant qu'utilisateur root avec sudo nano / etc / profile. Si vous le modifiez d'une autre manière, le système se plaindra d'un / etc / profile endommagé, même si vous changez les permissions en root.

Ilias
la source
7
L'ajout de variables d'environnement au profil est très inférieur car il n'affecte que les processus shell.
UloPe
-5

J'ai ajouté les variables dans le ~ / .bash_profile de la manière suivante. Une fois que vous avez terminé, redémarrez / déconnectez-vous et connectez-vous

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

REMARQUE: sans redémarrage / déconnexion et connexion, vous pouvez appliquer ces modifications en utilisant;

source ~/.bash_profile
Robin
la source
Notez que vous n'êtes pas obligé de vous déconnecter et de vous reconnecter. Utilisez simplement la commande source ie source .bash_profile.
Michael
2
En outre, le problème avec cette méthode est que vous devez toujours ouvrir un terminal avant que les variables d'environnement ne soient disponibles. Mieux vaut faire ce qui est dans la première réponse pour qu'ils soient disponibles sans avoir à ouvrir un terminal.
Michael
1
Cela ne fonctionne pas sur les applications chargées via SpotLight. stackoverflow.com/questions/135688/…
Rasika Perera
1
L'utilisation des fichiers de configuration bash est d'une aide limitée car elle suppose que vous avez toujours bash comme ancêtre du processus dont l'environnement que vous essayez d'effectuer. Spotlight, le finder, emacs, xcode, cronjobs, agents launchd, tout IDE, navigateurs de contrôle de source, etc. etc. tous n'auront pas bash comme ancêtre. Le seul processus qui peut couvrir ces derniers de manière cohérente est launchd.
Ben Hyde