Definir variáveis ​​de ambiente via launchd.conf não funciona mais no OS X Yosemite / El Capitan / macOS Sierra / Mojave?

189

Parece que o launchd.conf que não carrega mais minha variável de ambiente. Alguém mais notou aquilo?

Existe outra solução para definir permanentemente variáveis ​​de ambiente?

Tosh
fonte
Ele faz o trabalho e tornar-se disponível no aplicativo, mas não no terminal
Chang Zhao

Respostas:

158

Crie um environment.plistarquivo ~/Library/LaunchAgents/com este conteúdo:

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

Você pode adicionar muitos launchctlcomandos dentro do <string></string>bloco.

O plistserá ativado após a reinicialização do sistema. Você também pode usar launchctl load ~/Library/LaunchAgents/environment.plistpara iniciá-lo imediatamente.

[Editar]

A mesma solução também funciona em El Capitan.

O Xcode 7.0+ não avalia variáveis ​​de ambiente por padrão. O comportamento antigo pode ser ativado com este comando:

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

[Editar]

Existem algumas situações em que isso não funciona. Se o computador for reiniciado e a opção "Reabrir janelas ao fazer login novamente" estiver selecionada, as janelas reabertas talvez não vejam as variáveis ​​(talvez elas estejam abertas antes da execução do agente). Além disso, se você efetuar login via ssh, as variáveis ​​não serão definidas (portanto, será necessário configurá-las em ~ / .bash_profile). Finalmente, isso não parece funcionar para a PATH em El Capitan e Sierra. Isso precisa ser definido via 'launchctl config user path ...' e em / etc / caminhos.

MortimerGoro
fonte
20
Não há necessidade de reiniciar! Você pode executar o "launchctl start environment.plist" e reiniciar o aplicativo necessário para obter os novos env
;;
1
Isso não funcionaria com a variável PATH para mim. Portanto, além dessa abordagem para definir outras variáveis, defino a variável PATH no meu ~ / .bash_profile. Isso pode não funcionar para todos os casos, mas até agora não tenho nenhum problema.
djule5
6
Descobri-lo: a trabalhar sem reiniciar, ele deve ser "launchctl carga environment.plist", não começar
Dave Hartnoll
2
Ah sim. Nada como uma configuração obscura que aparece exatamente 9 vezes em toda a Internet (google UseSanitizedBuildSystemEnvironment).
Ohad Schneider
2
Funciona em Sierra bem
Shwouchk
64

[ Resposta original ]: Você ainda pode usar launchctl setenv variablename valuepara definir uma variável para que seja escolhida por todos aplicativos (aplicativos gráficos iniciados pelo Dock ou Spotlight, além dos iniciados pelo terminal).

Obviamente, você não vai querer fazer isso toda vez que fizer login.

[ Editar ]: Para evitar isso, inicie AppleScript Editor, digite um comando como este:

do shell script "launchctl setenv variablename value"

(Use várias linhas se desejar definir várias variáveis)

Agora salve ( + s) como formato de arquivo: Aplicativo . Por fim, abra System SettingsUsuários e gruposItens de login e adicione seu novo aplicativo.

[ Resposta original ]: Para contornar este local, todas as variáveis ​​que você deseja definir em um breve script de shell, consulte esta resposta anterior sobre como executar um script no login do MacOS . Dessa forma, o script será chamado quando o usuário efetuar login.

[ Editar ]: Nenhuma solução é perfeita, pois as variáveis ​​serão definidas apenas para esse usuário específico, mas espero / acho que isso pode ser tudo o que você precisa.

Se você tiver vários usuários, poderá definir manualmente um Item de Login para cada um deles ou colocar uma cópia de com.user.loginscript.plist em cada um de seus Library / LaunchAgents locais diretórios , apontando para o mesmo script de shell.

Concedido, nenhuma dessas soluções alternativas é tão conveniente quanto /etc/launchd.conf .

[ Edição adicional ]: Um usuário abaixo menciona que isso não funcionou para ele. No entanto, eu testei em várias máquinas Yosemite e funciona para mim. Se você estiver tendo um problema, lembre-se de que precisará reiniciar os aplicativos para que isso entre em vigor. Além disso, se você definir variáveis ​​no terminal via ~ / .profile ou ~ / .bash_profile , elas substituirão as coisas definidas via launchctl setenv para aplicativos iniciados no shell .

ruario
fonte
5
Pelo que sei, uma desvantagem dessa técnica é que as variáveis ​​não serão definidas para nenhum outro aplicativo iniciado no login. Por exemplo, se você abrir Terminal, a variável será definido, mas se você fizer logoff e ligado novamente, tendo Terminal reiniciar automaticamente, a variável será desactivado ...
JasonD
Eu tentei esta solução e também não funcionou para mim. Mas estou especificamente esperando que meu Java IDE (IntelliJ) pegue minhas modificações de caminho e não é. Tudo funciona muito bem no terminal. Pode ser um bug no IntelliJ. Ainda frustrante que a Apple tenha removido essa funcionalidade. Liguei para a Apple e eles não foram muito úteis.
Jason
Isso está funcionando para mim, mas você sabe o que fazer para adicionar também as variáveis ​​de ambiente ao sudo?
etennienel 11/11
2
Isso funcionará em geral, no entanto, há um erro no Yosemite (10.10.0 e 10.10.1 pelo menos) em que a configuração do $ PATH não funciona dessa maneira. A Apple está ciente do bug. Atualmente (a partir de 10.10.1), não há maneira conhecida de definir um $ PATH para aplicativos GUI em todo o sistema.
TJ Luoma
3
Depois de usar um dos métodos acima mencionados e reiniciar o laptop - Certifique-se de reabrir explicitamente os aplicativos (como iTerm, terminal, Eclipse, IDEA ou o que você estiver usando). Se você não os reiniciar explicitamente e se, durante a reinicialização do OSx, a caixa de seleção foi marcada como "Reiniciar janelas ao efetuar login novamente" (que é o padrão) - esses programas não lerão as novas variáveis ​​de ambiente.
Ran
21

É possível definir variáveis ​​de ambiente no Mac OS X 10.10 Yosemite com 3 arquivos + 2 comandos.

Arquivo principal com definição de variáveis ​​de ambiente:

$ 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ção de serviço para carregar variáveis ​​de ambiente para aplicativos do usuário (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>

A mesma definição de serviço para aplicativos de usuário raiz:

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

E, finalmente, devemos registrar estes serviços:

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

O que temos:

  1. O único local para declarar variáveis ​​de ambiente do sistema: / etc / environment
  2. Atualização automática instantânea de variáveis ​​de ambiente após a modificação do arquivo / etc / environment - basta reiniciar o aplicativo

Questões / problemas:

Para que suas variáveis ​​env sejam corretamente tomadas pelos aplicativos após a reinicialização do sistema, você precisará:

  • faça o login duas vezes: login => logout => login
  • ou feche e reabra aplicativos manualmente, onde variáveis ​​env devem ser obtidas
  • ou NÃO use o recurso "Reabrir janelas ao fazer logon novamente".

Isso acontece porque a Apple nega a ordem explícita dos serviços carregados, portanto as variáveis ​​env são registradas paralelamente ao processamento da "fila de reabertura".

Mas, na verdade, reinicializo meu sistema apenas várias vezes por ano (em grandes atualizações), portanto não é grande coisa.

ursa
fonte
Boa ideia. Eu tentei e funciona para a maioria das variáveis ​​de ambiente (como JAVA_HOME), mas não para a PATHvariável (veja minha pergunta em perguntar diferente ).
Halloleo 28/10
4
PATH deve ser definido com o arquivo / etc / caminhos. Basta adicionar seu caminho personalizado ao final deste arquivo.
ursa
Eu não estou tão familiarizado com isso launchd, mas não seria possível carregar esses Daemons na inicialização (ou seja, antes do login)? Isso deve contornar todos os problemas que você menciona.
Egon
Adoro a abordagem acima, mas tenho um problema estranho para gerenciar. Após a reinicialização, um genet VARNAME retorna o valor correto, mas o eco $ VARNAME não retorna nada. O que pode ser uma razão para isso? Eu postei isso para stackoverflow.com/questions/27045137/... bem e espero que alguém aqui tem uma idéia
CTP
Verifique se as permissões de arquivo do / etc / environment são as descritas acima.
Imanuelcostigan
6

Citado de

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

Após muita deliberação, a engenharia removeu esse recurso. O arquivo /etc/launchd.conffoi removido intencionalmente por motivos de segurança. Como solução alternativa, você pode executar launchctl limitcomo root cedo durante a inicialização, talvez a partir de LaunchDaemon. (...)

Solução:

Coloque o código no /Library/LaunchDaemons/com.apple.launchd.limit.plistbash-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
fonte
1
Você pode explicar isso um pouco mais? Não consigo ver como o 'Resolver problema' se relaciona com o problema inicial!
Nick H247
Não é o OP, mas acho que a essência aqui é: coloque essa lista /Library/LaunchDaemonse, em vez de dizer launchctlpara executar o limitcomando, diga para executar o setenvcomando com PATHuma string de caminho como argumentos. launchddeve buscá-lo automaticamente na inicialização e se auto-modificar quase imediatamente.
Laird Nelson
5
O xml é copiado incompletamente. A linha doctype deve ler<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
UloPe
6
@ax, que parte desse argumento realmente define uma variável de ambiente?
HairOfTheDog
3

Aqui estão os comandos para restaurar o comportamento antigo:

# 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

Agora você pode especificar comandos como setenv JAVA_HOME /Library/Java/Homeem /etc/launchd.conf.

Verificado em El Capitan.

yanchenko
fonte
2

O que funcionou para mim (inspirado nos agradecimentos de aax):

Cole isso em /Library/LaunchDaemons/com.apple.launchd.limit.plist e reinicie:

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

Se você precisar passo a passo:

  • Terminal de lançamento
  • Digite sudo su e digite sua senha para fazer login como root
  • Digite vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
  • No editor vi, pressione a tecla i para entrar no modo de inserção e cole o conteúdo exato do código acima (⌘+v ). Isso forçará o limite para 16384 arquivos por processo e 16384 arquivos no total
  • Salve o arquivo e sair usando esc, em seguida,:wq
  • Reinicialize seu sistema e verifique se está funcionando usando o comando launchctl limit

Espero que isso tenha ajudado.

Baptiste
fonte
10
O que essa solução tem a ver com a definição de variáveis ​​de ambiente?
HairOfTheDog
2

Você pode tentar https://github.com/ersiner/osx-env-sync . Ele lida com aplicativos de linha de comando e GUI de uma única fonte e funciona com a versão mais recente do OS X (Yosemite).

Você pode usar substituições de caminho e outros truques de shell, já que o que você escreve é ​​um script bash regular a ser originado pelo bash em primeiro lugar. Sem restrições .. (Verifique a documentação do osx-env-sync e você entenderá como isso ocorre).

Respondi a uma pergunta semelhante aqui, onde você encontrará mais.

Ersin Er
fonte
-3

A solução é adicionar sua variável a /etc/profile. Então tudo funciona como esperado! Claro que você DEVE fazê-lo como usuário root com o sudo nano / etc / profile. Se você editá-lo de qualquer outra maneira, o sistema irá reclamar com um perfil / etc / danificado, mesmo que você altere as permissões para root.

Ilias
fonte
7
A adição de variáveis ​​de ambiente ao perfil é muito inferior, pois afeta apenas os processos do shell.
UloPe
-5

Eu adicionei as variáveis ​​no ~ / .bash_profile da seguinte maneira. Após concluir, reinicie / efetue logout e efetue login

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

NOTA: sem reiniciar / sair e fazer login, você pode aplicar essas alterações usando;

source ~/.bash_profile
Robin
fonte
Observe que você não precisa sair e entrar novamente. Basta usar o comando source, ou seja, source .bash_profile.
Michael
2
Além disso, o problema com esse método é que você ainda precisa abrir um terminal antes que as variáveis ​​de ambiente estejam disponíveis. É melhor fazer o que está na primeira resposta para que eles estejam disponíveis sem a necessidade de abrir um terminal.
Michael
1
Isso não funciona em aplicativos carregados via SpotLight. stackoverflow.com/questions/135688/…
Rasika Perera
1
O uso dos arquivos de configuração do bash é de pouca ajuda, pois presume que você sempre tenha o bash como um ancestral do processo, cujo ambiente está tentando afetar. O Spotlight, o localizador, emacs, xcode, cronjobs, agentes launchd, qualquer IDE, navegadores de controle de origem etc. etc., todos não terão o bash como ancestral. O único processo que pode abranger esses consistentes é o launchd.
Ben Hyde