Por que os shells interativos nos shells de login do OSX são padrão?


43

No Linux e, que eu saiba, todos os sistemas Unix, emuladores de terminal executam shells interativos e sem login por padrão. Isso significa que, para o bash, o shell iniciado irá:

Quando um shell interativo que não é um shell de login é iniciado, o bash lê e executa comandos de /etc/bash.bashrce ~/.bashrc, se esses arquivos existirem. Isso pode ser inibido usando a --norc opção

A --rcfile opção file forçará o bash a ler e executar comandos do arquivo em vez de /etc/bash.bashrce ~/.bashrc.

E para shells de login:

Quando o bash é chamado como um shell de logon interativo ou como um shell não interativo com a --loginopção, ele primeiro lê e executa comandos do arquivo /etc/profile, se esse arquivo existir. Depois de ler esse arquivo, ele procura ~/.bash_profile, ~/.bash_logine ~/.profile, nessa ordem, e lê e executa os comandos do primeiro que existe e é legível.

A --noprofileopção pode ser usada quando o shell é iniciado para inibir esse comportamento.

No OSX, no entanto, o shell padrão (que é o bash) iniciado no terminal padrão (Terminal.app) na verdade origina ~/.bash_profileou ~.profileetc. Em outras palavras, ele atua como um shell de logon.

Pergunta principal : Por que o shell interativo padrão é um shell de login no OSX? Por que a OSX escolheu fazer isso? Isso significa que todas as instruções / tutoriais para itens baseados em shell que mencionam a alteração de itens ~/.bashrcfalharão no OSX ou vice-versa ~/.profile. Ainda assim, enquanto muitas acusações podem ser feitas na Apple, a contratação de desenvolvedores incompetentes ou idiotas não é uma delas. Presumivelmente, eles tinham uma boa razão para isso, então por quê?

Subquestions: O Terminal.app realmente executa um shell de logon interativo ou mudou o comportamento do bash? Isso é específico do Terminal.app ou é independente do emulador de terminal?


2
O Terminal.app executa um shell de logon. Não sei por que a Apple escolheu fazer isso.
Gilles 'SO- stop be evil'

A propósito, a partir do macOS Catalina , o shell padrão é zsh .
Basil Bourque

Respostas:


33

A maneira como ele deve funcionar é que, no momento em que você recebe um prompt de shell, ambos .profilee .bashrcforam executados. Os detalhes específicos de como chegar a esse ponto são de relevância secundária, mas se um dos arquivos não for executado, você terá um shell com configurações incompletas.

O motivo pelo qual os emuladores de terminal no Linux (e em outros sistemas baseados em X) não precisam ser executados .profileé que normalmente já foram executados quando você efetuou login no X. As configurações .profiledevem ser do tipo que pode ser herdado por subprocessos, portanto, desde que seja executado uma vez quando você efetuar login (por exemplo, via .Xsession), quaisquer outros subshells não precisarão executá-lo novamente.

Como a página wiki Debian vinculada por Alan Shutko explica:

"Por que , então, é .bashrcum arquivo separado .bash_profile? Isso é feito principalmente por razões históricas, quando as máquinas eram extremamente lentas em comparação com as estações de trabalho de hoje. O processamento dos comandos .profileou .bash_profilepode levar muito tempo, especialmente em uma máquina onde grande parte do trabalho teve que ser feito por comandos externos (pré-bash). Portanto, os difíceis comandos de configuração inicial, que criam variáveis ​​de ambiente que podem ser passadas para processos filhos, são inseridos .bash_profile. As configurações e aliases transitórios que não são herdados são colocados. no .bashrcde modo que possam ser re-lido por todos os subshell ".

Todas as mesmas regras também são válidas para o OSX, exceto por uma coisa - a GUI do OSX não é executada .profilequando você faz login, aparentemente porque tem seu próprio método de carregar configurações globais. Mas isso significa que um emulador de terminal no OSX faz necessidade de correr .profile(dizendo ao shell lança que é um shell de login), caso contrário você pode acabar com uma concha potencialmente aleijado.


Agora, uma espécie de peculiaridade boba do bash, não compartilhada pela maioria dos outros shells, é que ele não será executado automaticamente .bashrcse for iniciado como um shell de login. A solução padrão para isso é incluir algo como os seguintes comandos em .bash_profile:

[[ -e ~/.profile ]] && source ~/.profile    # load generic profile settings
[[ -e ~/.bashrc  ]] && source ~/.bashrc     # load aliases etc.

Como alternativa, é possível não ter nenhum .bash_profile, e apenas inclua algum código específico do bash no .profilearquivo genérico para executar, .bashrcse necessário.

Se o OSX usar .bash_profilecomo padrão ou .profile não fizer isso, é sem dúvida um bug. De qualquer forma, a solução alternativa adequada é simplesmente adicionar essas linhas a .bash_profile.


Edit: Como observa Strugee , o shell padrão no OSX costumava ser o tcsh, cujo comportamento é muito mais saudável a esse respeito: quando executado como um shell de login interativo, o tcsh lê automaticamente ambos .profile e .tcshrc / .cshrce, portanto, não precisa de nenhuma solução alternativa, como o .bash_profiletruque Mostrado acima.

Com base nisso, tenho 99% de certeza de que a falha do OSX em fornecer um padrão apropriado .bash_profileé porque, quando eles mudaram do tcsh para o bash, o pessoal da Apple simplesmente não percebeu essa verruga no comportamento de inicialização do bash. Com o tcsh, esses truques não eram necessários - iniciar o tcsh como um shell de login em um emulador de terminal OSX Just Plain Works e faz a coisa certa sem esses kluges.


1
Obrigado, eu meio que sabia tudo isso. Minha pergunta é por que o OSX optou por configurar de forma a tornar .bashrcirrelevante? Por que eles escolheram fazer todos os shells fazer login em shells? Até onde eu sei, apenas sua última frase trata disso e apenas diz que é um bug.
terdon

1
Não, o problema é que eles iniciam shells de login em seus emuladores de terminal. Os dotfiles são o comportamento padrão do bash, os shells de login iniciais lerão o perfil etc., não o bashrc etc. A questão é por que os shells de login são executados em vez dos que não são de login.
terdon

2
Sim, e eu e Alan explicamos que é porque, diferentemente do Linux, o OSX não é executado .profilequando o usuário efetua login na GUI, portanto, eles precisam executá-lo posteriormente para obter variáveis ​​de ambiente como $PATH, normalmente definidas .profile, configuradas corretamente . O fato de que, como efeito colateral, isso faz com que .bashrcnão seja fornecido, é um bug; você pode discutir se é um bug no bash ou no OSX, mas isso não muda o fato de que o comportamento correto seria garantir que as variáveis ​​de ambiente .profilee a configuração do bash .bashrcsejam carregadas.
Ilmari Karonen 14/03

1
Ter .bashrcfonte .profileseria uma péssima idéia, pois faria com que cada sub-shell fosse executado novamente .profile. Se nada mais, isso faria com que os .profileidiomas comuns export PATH = "$HOME/bin:$PATH"continuassem com entradas redundantes $PATH. Ter .profileorigem .bashrcfaz muito mais sentido, mas somente depois de verificar se o shell em que está sendo executado é, de fato, bash. Ter .bash_profilefonte de ambos .profile e .bashrc , como sugeri acima, é a IMO, a opção mais sensata.
Ilmari Karonen 14/03

2
E eu estou dizendo a resposta para "por que eles usam um shell de login?" é "porque eles precisam carregar .profile", enquanto a resposta para "por que eles não são .bashrcoriginários .profile?" é "porque é um bug!" Sério, isso não pode ser uma decisão intencional; é apenas algo que eles ignoraram, presumivelmente porque, no ecossistema Mac, os projéteis são cidadãos de segunda classe com os quais a maioria dos usuários não deveria lidar. (. Ps Ver também a resposta de strugee para uma explicação histórica, é quase certamente uma regressão do interruptor de tcsh para bash.)
Ilmari Karonen

14

A principal razão pela qual os aplicativos do terminal X executam shells sem login por padrão é que, no início dos tempos, sua .Xsession executaria o .profile para configurar seus itens de login iniciais. Então, como tudo já estava configurado, os aplicativos de terminal não precisavam executá-lo, eles podiam executar o .bashrc. A discussão sobre por que isso importaria está em https://wiki.debian.org/DotFiles :

Vamos considerar o xdm como um exemplo. pierre volta das férias um dia e descobre que o administrador do sistema instalou o xdm no sistema Debian. Ele efetua login muito bem e o xdm lê seu arquivo .xsession e executa o fluxbox. Tudo parece estar bem até que ele receba uma mensagem de erro no local errado! Como ele substitui a variável LANG em seu .bash_profile e como o xdm nunca lê .bash_profile, sua variável LANG agora está definida como en_US em vez de fr_CA.

Agora, a solução ingênua para esse problema é que, em vez de iniciar o "xterm", ele poderia configurar seu gerenciador de janelas para iniciar o "xterm -ls". Este sinalizador informa ao xterm que, em vez de iniciar um shell normal, ele deve iniciar um shell de login. Sob essa configuração, o xterm gera / bin / bash, mas coloca "- / bin / bash" (ou talvez "-bash") no vetor de argumento; portanto, o bash age como um shell de login. Isso significa que toda vez que ele abrir um novo xterm, ele lerá / etc / profile e .bash_profile (comportamento bash embutido) e, em seguida, .bashrc (porque .bash_profile diz para fazer isso). Isso pode parecer funcionar bem no começo - seus arquivos de ponto não são pesados, então ele nem percebe o atraso - mas há um problema mais sutil. Ele também lança um navegador da web diretamente do menu do fluxbox, e o navegador da Web herda a variável LANG do fluxbox, que agora está definido como o código de idioma errado. Portanto, enquanto seus xterms podem estar bem, e qualquer coisa lançada a partir dele pode estar bem, seu navegador ainda está fornecendo páginas no local errado.

No OS X, os ambientes de usuário não são iniciados por uma pilha de scripts de shell, e o launchd não gera .profile a qualquer momento. (Isso é uma pena, pois significa que é muito mais irritante definir variáveis ​​de ambiente, mas a vida é assim.) Como isso não acontece, quando seria executado .profile? se você entrar? Isso parece meio inútil, já que muitas caixas nunca serão alvos de ssh. Também pode fazer com que os terminais executem shell de login por padrão, para que o .profile seja executado em algum momento.

E o .bashrc, então? Isso é inútil? Não. Ele ainda tem o objetivo que tinha nos dias do VT100. É usado sempre que você abre um shell que não seja a janela do Terminal. Portanto, se você sair do Emacs ou vi, ou se fizer um usuário su.


1
A página Debian que você está citando explica por que as .profilefontes do Debian .bashrc, não por que o OSX decidiu fazer todos os shells fazer login por padrão. Na verdade, você está respondendo a outra pergunta minha , e obrigado! No entanto, sua resposta não explica a opção OSX e a citação do Debian é completamente irrelevante aqui, tanto quanto eu posso dizer (por favor, deixe-me saber se estou apenas perdendo o ponto). A maneira OSX torna o .bashrcetc inútil e não o torna .profilemais útil.
terdon

4

Não sei por que eles teriam feito isso. No entanto, aqui está o meu palpite.

Para começar, vale a pena notar que em um sistema GNU / Linux, é claro que você pode mudar para vt1, vt2, etc. Você obtém um shell de login lá. Em um sistema OS X, não há equivalente. A única maneira de acessar os fundamentos do UNIX é através de um emulador de terminal ou através do modo de usuário único (exoneração de responsabilidade: nunca usei o modo de usuário único; é o IIRC controlado por linha de comando, mas posso estar errado). Portanto, no OS X, qualquer que seja o padrão no emulador, é o padrão para todo o sistema.

Agora, por que você tornaria o padrão um shell de login? Existem algumas razões (leia-se: não muitas) para pensar nisso.

  • Ele fornece uma experiência consistente ao usuário se você fizer o SSH na caixa. (Especialmente importante para a edição para servidores do OS X - presumivelmente, se você estiver executando um servidor OS X, você é um novato.)
  • O shell padrão do OS X costumava ser tcsh. Esse é um palpite o mais selvagem possível, mas pode ser que tcshnormalmente algo tenha acontecido quando executado como um shell de login, e o padrão histórico permaneceu. (Duvido, no entanto - talvez um dos regulares mais velhos pudesse nos dizer.)
  • "Somos a Apple. Somos os fornecedores da maior distribuição UNIX do planeta. Não importa quão triviais sejam nossos motivos; se tomarmos uma decisão, sua ferramenta deverá lidar com isso".

Honestamente, eu uso o Darwin há ~ 6 anos e não consigo responder a essa pergunta corretamente. Realmente não faz sentido para mim também.

Para responder à sua subquestão, bashnão está corrigido nem nada (pelo menos para isso). O emulador de terminal padrão executa shells de login por padrão e, presumivelmente, o iTerm copia isso.


1
+1 por mencionar o tcsh, já que seu comportamento é muito mais saudável a esse respeito do que o bash: quando iniciado como um shell de login interativo, o tcsh obtém fontes tanto .profile e .tcshrc/ .cshrcsem exigir kluges como o que eu dei na minha resposta. Dado isso, suspeito que esse comportamento seja uma regressão não corrigida causada pela mudança de tcsh para bash.
Ilmari Karonen 14/03

@IlmariKaronen Você quer dizer (aqui e ali ) que fontes tcsh .logine .tcshrc/ .cshrc? Não faria sentido que o tcsh fosse fonte .profile; normalmente contém comandos com shsintaxe que tcshnão serão aceitos. Não tenho macOS, mas fiz /bin/tcshmeu shell de login no Ubuntu 16.04. .profilenão é originário. O tcsh (1) não menciona esse arquivo, nem o tcsh (1) .
Eliah Kagan 17/10

3

Esta é uma atualização para o status atual: as respostas ficaram obsoletas à medida que novas versões do MacOSX foram lançadas e o comportamento do login foi alterado.

Esta pergunta foi feita e respondida em 2014. Pesquisei o assunto na tentativa de criar um conjunto .bashrc e .bash_profile comum para usar em diferentes distribuições Linux e BSD (como eles chamam, se não forem distribuições).

Recentemente, comprei um Mac Mini usado com o Sierra instalado, agora tenho sistemas com 10.6, 10.10, 10.11 e 10.12. Embora eu tenha analisado os mais antigos (deixando pistas sobre o status anterior), a instalação do 10.12 Sierra é intocada.

Resultados: No 10.12 Sierra, NÃO há .bashrc, .bash_profile ou .profile padrão criados. No / etc, existem bashrc, bashrc_Apple_Terminal e profile. Conteúdo de / etc / profile:

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

Conteúdo de / etc / bashrc:

# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
   return
fi

PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize

[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"

O script / etc / bashrc_Apple_Terminal define a variável PROMPT_COMMAND e define um mecanismo para preservar o estado da sessão para cada terminal; se o aplicativo do terminal for encerrado, o status da sessão anterior será restaurado quando o aplicativo for reiniciado. Caso contrário, quase nada ($ PS1 mínimo) é definido em / etc / bashrc, deixando qualquer outra personalização ($ PS1 real, aliases, funções) a ser definida nas configurações ~ / .bashrc e $ PATH em .bash_profile (ou em .profile , proveniente de .bash_profile).

Confirmei que o iTerm2 se comporta da mesma maneira que o aplicativo Terminal, exceto que o comportamento padrão de iniciar uma sessão de logon é visível e pode ser editado.

Se você executar uma sessão de terminal X11 (agora XQuartz) XTerm, verá uma sessão sem login, a mesma de um sistema Linux; .bash_profile (ou .profile) é ignorado e você obtém .bashrc.

E aqui está a minha resposta:

Embora o aplicativo Terminal afirme ser um xterm (TERM = xterm-256color), ele não define a variável $ DISPLAY a menos que o X11 esteja instalado. Estamos vendo uma simulação de um ambiente X, mas não completamente real. Se você fizer o SSH em outro sistema com a opção -X (ativar o encaminhamento do X11), ela falhará porque não há variável $ DISPLAY. Se você instalou o X11 e, em seguida, o SSH em outro sistema, o encaminhamento do X11 será bem-sucedido.

Conclusão (e resposta curta): o aplicativo Terminal não é um terminal X11 verdadeiro (não define $ DISPLAY); ele se comporta muito mais como um logon SSH do que uma sessão XTerm, pois deve ser uma sessão de logon para definir valores de / etc / profile e ~ / .bash_profile ou ~ / .profile


0

As respostas acima explicado a razão pela qual conchas interativos são shells de login no MacOS por padrão: ajustes no /etc/profile, ~/.profilesão herdadas por um escudo non-login em sistemas baseados em X, mas não no MacOS . Aqui, quero lembrar que você deve sempre usar o shell de login no macOS devido à existência de path_helper:

 cat /etc/profile # or cat /etc/zprofile
# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

O path_helperutilitário lê o conteúdo dos arquivos nos diretórios /etc/paths.de /etc/manpaths.d e acrescenta seu conteúdo para o PATHe MANPATHambientais variáveis, respectivamente. (A MANPATHvariável de ambiente não será modificada, a menos que já esteja definida no ambiente.)

Se você estiver usando um shell sem login, alguns caminhos não serão importados.

Eu acho que é sempre uma boa ideia para o desenvolvedor colocar um arquivo /etc/paths.dpara importar seus valores de caminho, mas não para vincular os binários solicitáveis ​​em locais como /usr/binou /bin. (O padrão PATHé /usr/bin:/bin:/usr/sbin:/sbin. Nem todo mundo usa o Homebrew ou o MacPorts adicionando valores personalizados PATH. Portanto, nem sempre há um lugar seguro para colocar os links simbólicos dos comandos que podem ser chamados.)

Aqui está um exemplo de arquivos em /etc/paths.d. Basicamente, você está colocando um valor por linha.

 cat /etc/paths.d/Wireshark
/Applications/Wireshark.app/Contents/MacOS

Referência:

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.