Variáveis ​​de ambiente em bash_profile ou bashrc?

36

Encontrei esta pergunta [blog]: Diferença entre .bashrc e .bash_profile muito útil, mas depois de ver a resposta mais votada (muito boa por falar nisso), tenho mais perguntas. No final da resposta mais votada, correta, vejo a declaração da seguinte forma:

Observe que você pode ver aqui e ali recomendações para colocar definições de variáveis ​​de ambiente em ~ / .bashrc ou sempre iniciar shells de login nos terminais. Ambos são más idéias.

  1. Por que é uma má idéia (não estou tentando lutar, só quero entender)?

  2. Se eu quiser definir uma variável de ambiente e adicioná-la ao PATH (por exemplo, JAVA_HOME), onde seria o melhor local para colocar a entrada de exportação? em ~ / .bash_profile ou ~ / .bashrc ?

  3. Se a resposta à pergunta número 2 for ~ / .bash_profile , então eu tenho mais duas perguntas:

    3.1 O que você colocaria em ~ / .bashrc ? apenas aliases?

    3.2 Em um shell que não é de login, acredito que o ~ / .bash_profile não está sendo "captado". Se a exportação da entrada JAVA_HOME estivesse em bash_profile, eu seria capaz de executar os comandos javac & java ? Encontrá-los-ia no CAMINHO? É por isso que algumas postagens e fóruns sugerem a configuração de JAVA_HOME e da mesma forma para ~ / .bashrc ?

    Desde já, obrigado.

Viriato
fonte

Respostas:

26

Em um sistema moderno, não é especialmente comum encontrar os casos em que isso importa, mas acontece. (Em particular, se você usar operações de shell vimcomo, por exemplo, :r !commandou em linha !<motion>command).

O que você colocaria em ~ / .bashrc? apenas aliases?

Você coloca coisas ~/.bashrcque não seriam herdadas por subshells automaticamente; isso significa aliases e funções, principalmente, embora algumas vezes você tenha configurações variáveis ​​que não deseja que sejam visíveis fora do shell (isso é muito raro). Pode-se argumentar que essas devem ser exportadas de alguma forma, mas várias tentativas experimentais tiveram problemas de compatibilidade com a tentativa de escondê-las no ambiente e foram abandonadas.

Se eu quiser definir uma variável de ambiente e adicioná-la ao PATH (por exemplo, JAVA_HOME), onde seria o melhor local para colocar a entrada de exportação? em ~ / .bash_profile ou ~ / .bashrc?

Você coloca as configurações do ambiente ~/.bash_profilepara que elas recebam configurações iniciais sãs. Às vezes, você deseja substituí-las (geralmente isso é feito por ambientes complexos, como Matlab ou Cadence); se você colocar as configurações do ambiente ~/.bashrc, os shells executados a partir desses ambientes perderão as personalizações do ambiente, e as coisas poderão não funcionar corretamente como resultado. Isso também se aplica se você usar um pacote como módulos , virtualenv , rvm etc. para gerenciar vários ambientes de desenvolvimento; colocar suas configurações ~/.bashrcsignifica que você não pode executar o ambiente que deseja dentro do seu editor, mas será forçado a entrar no padrão do sistema.

Em um shell que não é de login, acredito que o ~ / .bash_profile não está sendo "captado".

Isto está correto; você normalmente deseja que o shell inicial seja um shell de logon e que quaisquer shells iniciados sob esse não sejam shells de logon. Se o shell inicial não for um shell de logon, você não terá um padrão PATHou várias outras configurações (incluindo o seu JAVA_HOMEexemplo).

A maioria dos ambientes de área de trabalho iniciados por gerenciadores de exibição (ou seja, a grande maioria dos logins gráficos) não configura um ambiente de logon para toda a área de trabalho; portanto, você é forçado a executar o shell inicial nos terminais como um shell de logon. Isso causa uma série de problemas (especialmente que o PATHdisponível para os programas executados a partir de painéis não está configurado corretamente, porque o painel não é um terminal e não foi executado ~/.bash_profile), mas é um compromisso razoável, uma vez que nem sempre é possível executar com segurança ~/.bash_profileno ambiente não interativo no início de uma sessão iniciada por um gerente de exibição, dependendo do seu conteúdo. Às vezes, é recomendável colocar as configurações do ambiente em~/.bashrcem vez de configurar um shell de login; como discutido acima, isso funciona, desde que você não precisa substituir esse ambiente, e provoca rupturas ímpares uma vez que você fazer necessidade de fazê-lo.

Recentemente, ajudei a diagnosticar um problema como este no OS X em que um usuário que havia colocado as configurações ~/.bashrcmais tarde começou a usar rvme o perlbrew viu um comportamento estranho, porque os ambientes configurados pelos dois foram "desfeitos" pelos ~/.bashrceditores internos e sudo(que no OS X , ao contrário do Linux, propaga o usuário $HOMEpara que ele ~/.bashrcseja executado pelo shell raiz). Antes de tentar usar esses ambientes, não havia problema; ao começar a usá-los, ficaram perplexos com a perda inesperada de suas configurações.

geekosaur
fonte
11
Acho que entendi, talvez precise ler mais vezes para internalizá-lo mais, mas estou concluindo o seguinte. Em ambientes corporativos, a fim de ter um controle mais preciso dos shells customizados sem efeitos colaterais do global, é uma prática recomendada colocar variáveis ​​de ambiente em ~ / .bash_profile . Em um ambiente pessoal como o Ubuntu ou Linux Mint para que o PATH esteja definido corretamente, devo configurá-lo em ~ / .bashrc (ou mesmo em / etc / profile ). Estou correcto?
Viriato
Tem menos a ver com ambientes corporativos do que se você é apenas um usuário ou desenvolvedor; os sistemas gostam modulese rvmsão ferramentas de desenvolvedor, assim como Matlab e Cadence para definições um tanto diferentes de "desenvolvedor". De desenvolvimento simples também não obrigá-los, mas quando você precisa de teste contra várias versões de Ruby, Perl ou Python, então você realmente quer algo parecido rvm, perlbrewe virtualenv(respectivamente) em torno para ajudar a manter tudo em linha reta.
Geekosaur #
2

para ser sincero, há pouca diferença atualmente, apesar do que o guru tinha a dizer.

a questão por trás disso é que hoje em dia fazemos login graficamente, e não através de um shell de login. no passado, nós unix usuários gostamos de ver um breve relatório do que está acontecendo em um servidor imediatamente após o login - então iniciaremos o X por linha de comando - esse relatório geralmente requer algum tempo para gerar (por exemplo, 10 a 20 segundos). e depois não queremos ver o mesmo quando começamos, por exemplo, xterm. daí a diferença.

hoje em dia eu não acho que a distinção seja importante agora. Eu acho que hoje em dia se você usar o bashrc no bash_profile, ninguém poderá te culpar.

note que isso não se aplica ao macos x (todo terminal.app iniciado é um shell de login)

bubu
fonte
Não sei exatamente se entendi bem, mas no trabalho quando faço logon no ssh que é um shell de login, o bash_profile e o bashrc são originados, então acho que nesse caso não importa. Mas se eu entrar graficamente (o que isso significa)? como entrar no meu ubuntu pessoal?
Viriato
Concorde com a resposta do @bubu aqui - qualquer configuração em ~/.bash_profileque a fonte não ~/.bashrcseja muito difícil de trabalhar e quase danificada. Aplicativos gráficos de terminal significam que é mais simples usar apenas o ~ / .bashrc e colocar toda a configuração lá.
RichVel 21/03
1

Bem, sobre "Logins gráficos", depende de qual * DM você usa ...

Com o GDM (Gnome 3.18), tenho o seguinte:

/ etc / gdm / Xsession

#!/bin/sh   <= *important*

...

# First read /etc/profile and .profile
test -f /etc/profile && . /etc/profile
test -f "$HOME/.profile" && . "$HOME/.profile"
# Second read /etc/xprofile and .xprofile for X specific setup
test -f /etc/xprofile && . /etc/xprofile
test -f "$HOME/.xprofile" && . "$HOME/.xprofile"

Portanto, ~ / .profile é obtido no login usando / bin / sh e não / bin / bash

Existem dois casos

  1. / bin / sh está vinculado a / bin / bash, mas é executado no modo "POSIX / Bourne"
  2. / bin / sh é / bin / dash (debian / ubuntu). Mais rápido, mas com menos recursos (suporte ao ShellShock;) )

Portanto, o perfil / bin / sh é ~ / .profile e não ~ / .bash_profile, ~ / .zprofile

Este arquivo deve ser usado para configurações "agnósticas de shell" , como variáveis ​​de caminho e ambiente.

NENHUM programa executável para interação com o usuário somente para login deve estar aqui (verificação de correio, sorte, etc ...)

o ~ /.* rc é destinado apenas a sessões "interativas" (aliases, por exemplo ...)

Há uma diferença entre bash e zsh para shells de login interativos

bash origens apenas .bash_profile, enquanto zsh origens na ordem:

  1. ~ / .zprofile
  2. ~ / .zshrc
  3. ~ / zlogin (aqui estão disponíveis aliases definidos em ~ / .zshrc. no caso de shells "interativo" + "login"

A maneira correta de fazer ~ / .bash_profile foi respondida aqui:

Diferença entre .bashrc e .bash_profile

if [ -r ~/.profile ]; then . ~/.profile; fi
case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

Para habilitar teste (e criação de perfil), você pode usar este

~ / .bash_profile:

#!/bin/bash

# ------------------------------------------------
export _DOT_BASH_PROFILE_0=`date  --rfc-3339=ns`
# ------------------------------------------------

if [ -f ~/.profile ] ; then
    . ~/.profile
fi

case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

# ------------------------------------------------
export _DOT_BASH_PROFILE_1=`date  --rfc-3339=ns`
# ------------------------------------------------

~ / .zprofile:

#!/bin/zsh

# ------------------------------------------------
export _DOT_ZSH_PROFILE_0=`date  --rfc-3339=ns`
# ------------------------------------------------

if [ -f ~/.profile ] ; then
    . ~/.profile
fi

# no need to source, zsh already handle ~/.zshrc

###case "$-" in *i*) if [ -r ~/.zshrc ]; then . ~/.zshrc; fi;; esac

# ------------------------------------------------
export _DOT_ZSH_PROFILE_1=`date  --rfc-3339=ns`
# ------------------------------------------------

então, para testar:

chsh -s /bin/bash

ssh localhost
env

exit

ssh localhost env

ssh -t localhost bash -i -c env


chsh -s /bin/zsh

ssh localhost
env

exit

ssh localhost env

ssh -t localhost bash -i -c env

Então RVM / virtualenv deve entrar em ~ / .profile, IMHO

Mas isso não funciona , às vezes ...

Por exemplo, virualenvwrapper funciona apenas se o shell que estiver executando o Xsession for um bash "original" (exportando BASH_VERSION)

Se você estiver em um sistema de traço , a variável de ambiente e a configuração do caminho funcionarão, mas a definição da função virualenvwrapper não funcionará porque o script não é compatível com POSIX.

O script não apresenta nenhum erro, mas termina sem nenhuma definição de "trabalho" .

Portanto, você pode definir o ambiente em ~ / .profile , apenas para habilitar a execução correta do python a partir do cliente iniciada diretamente no X:

export VIRTUAL_ENV="/home/mike/var/virtualenvs/myvirtualenv"
export PATH="$VIRTUAL_ENV/bin:$PATH"
unset PYTHON_HOME

https://gist.github.com/datagrok/2199506

https://www.bountysource.com/issues/9061991-setting-up-your-computer-virtualenvwrapper-linux-all

Mas para virualenvwrapper, você tem duas alternativas:

  1. origine -o em ~ / .bash_profile ou ~ / .zprofile (ou ~ / .zlogin) quando o terminal atua como shell de login
  2. inclua o script em ~ / .bashrc ou ~ / zshrc

Isso significa que os clientes X (emacs por exemplo) devem ser iniciados a partir do shell do terminal e não do gráfico!

"Eu não posso ter satisfação ..."

hute37
fonte
Uma história completamente diferente está executando serviços com systemd Algumas alternativas possíveis são: escrever um script de wrapper , definir ambiente no arquivo de definição de "serviço" , despejar o ambiente em um arquivo "env" a ser originado em um shell pai. As coisas se torna mais complicado com RVM / virtualenv ...
hute37