Por que a origem remota do Bash .bash_profile em vez de .bashrc

24

O Bash Manual diz:

O Bash tenta determinar quando está sendo executado com sua entrada padrão conectada a uma conexão de rede, como quando executada pelo daemon de shell remoto, geralmente rshd, ou pelo daemon de shell seguro sshd. Se o Bash determinar que está sendo executado dessa maneira, ele lê e executa comandos de ~ / .bashrc, se esse arquivo existe e é legível.

Fontes deste Bash ~/.bashrc:

ssh user@host :

Mas este Bash fontes ~/.bash_profile:

ssh user@host

Não vejo diferença nesses dois comandos de acordo com as especificações. O stdin não está conectado a uma conexão de rede nos dois casos?

Cyker
fonte
2
Embora não seja o que você está perguntando, gostaria de observar que é uma boa prática obter o .bashrc em .bash_profile . Dessa forma, as configurações de .bashrc serão aplicadas independentemente de o bash ser iniciado como um shell de logon ou um shell que não seja de logon.
Ilmari Karonen

Respostas:

44

Um shell de logon primeiro lê /etc/profilee depois ~/.bash_profile.

Um shell sem login lê /etc/bash.bashrce depois ~/.bashrc.

Por que isso é importante?

Devido a esta linha em man ssh:

Se o comando for especificado, ele será executado no host remoto em vez de no shell de logon.

Em outras palavras, se o comando ssh tiver apenas opções (não um comando), como:

ssh user@host

Ele iniciará um shell de login, um shell de login será lido ~/.bash_profile.

Um comando ssh que possui um comando , como:

ssh user@host :

Onde o comando está :(ou não faz nada).
Ele não iniciará um shell de login, portanto ~/.bashrcé o que será lido.


Remote stdin

A conexão tty fornecida para / dev / stdin no computador remoto pode ser um tty real ou outra coisa.

Para:

$ ssh sorontar@localhost
/etc/profile sourced

$ ls -la /dev/stdin
lrwxrwxrwx 1 root root 15 Dec 24 03:35 /dev/stdin -> /proc/self/fd/0

$ ls -la /proc/self/fd/0
lrwx------ 1 sorontar sorontar 64 Dec 24 19:34 /proc/self/fd/0 -> /dev/pts/3

$ ls -la /dev/pts/3
crw--w---- 1 sorontar tty 136, 3 Dec 24 19:35 /dev/pts/3

Que termina em um TTY (não em uma conexão de rede) como o bash iniciado o vê.

Para uma conexão ssh com um comando:

$ ssh sorontar@localhost 'ls -la /dev/stdin'
sorontar@localhost's password: 
lrwxrwxrwx 1 root root 15 Dec 24 03:35 /dev/stdin -> /proc/self/fd/0

A lista de TTYs começa da mesma forma, mas observe que / etc / profile não foi originado.

$ ssh sorontar@localhost 'ls -la /proc/self/fd/0'
sorontar@localhost's password:
lr-x------ 1 sorontar sorontar 64 Dec 24 19:39 /proc/self/fd/0 -> pipe:[6579259]

O que informa ao shell que a conexão é um pipe (não uma conexão de rede).

Portanto, nos dois casos de teste, o shell não pode saber que a conexão é de uma rede e, portanto, não lê ~/.bashrc(se falamos apenas da conexão com uma rede). Ele lê ~ / .bashrc, mas por um motivo diferente.

sorontar
fonte
O caso no-arg também não seria qualificado para ser executado com sua entrada padrão conectada a uma conexão de rede e, portanto, ter ~/.bashrclido?
Cyker
@ Cyker Isso pressupõe que o shell tenha o stdin conectado a uma rede . Por que você assume isso? (Resposta editada, leia).
sorontar
A parte editada é interessante. Parece que o ssh não se incomoda com um pty ao simplesmente executar um comando.
Cyker
8

Você pergunta sobre o "por que" e não o "como", então tentarei responder dessa perspectiva. A seguir, apresentamos uma boa base de razões pelas quais as coisas aconteceram no passado para resultar em como elas acontecem hoje.


O motivo de ter dois arquivos de inicialização diferentes ("perfil" e "rc") é que, no passado, a maneira comum de trabalhar em uma máquina era:

  1. Faça login a partir de algum tipo de terminal real ou outra estação de trabalho e obtenha um shell de login . Esse shell invocará /etc/profilee ~/.profileconfigurará o ambiente para o usuário.

  2. Chame o ambiente em que o usuário deseja entrar. Esse ambiente poderia ser o Xorg, mas na maioria dos casos era um multiplexador como a tela GNU.

  3. O ambiente (por exemplo, tela GNU) invocaria shells extras (sem login) que herdam o ambiente do shell de login pai.

Essa foi a maneira comum de fazer login em uma máquina UNIX durante o tempo em cshe bashestavam sendo desenvolvidos. Portanto , foi considerado um desperdício ler ~/.profilenovamente as conchas que estavam herdando o ambiente de qualquer maneira.

bashadicionado ~/.bashrcpara configuração extra para esses shells que não são de login. csh(e tcsh) nunca adicionou nenhum tipo de arquivo "rc" para shells sem login. Observe que csh/ tcshnão são conchas compatíveis com o casco de bourne (que faz parte do POSIX) enquanto bashestiver. Outro shell compatível com bourne ksh, adicionou uma variável de ambiente (chamada ENV) que, se definida, seria usada como um arquivo de comandos de execução ("rc") para não-login ksh.

Então, sim, as versões mais recentes do bourne shells adicionaram o arquivo de configuração extra como uma conveniência para aliases e outras opções rápidas que estariam presentes dentro dos shells alterados pela tela GNU (ou similar), mas não presentes no shell que você obtém quando você entra pela primeira vez no arquivo. máquina.

Com o aumento dos gerenciadores de exibição gráfica (GDMs), a diferenciação entre os arquivos "profile" e "rc" ficou sem sentido porque o GDM teria seus próprios arquivos de inicialização (por exemplo, ~/.xinite ~/.xsession). Em seguida, os shells declarados dentro do GDM podem ser shells de login ou não, dependendo dos caprichos de um usuário, e o caso em que um shell sem login sempre teria um pai que é um shell de login não é mais verdadeiro.

Extra

Uma das minhas tabelas favoritas sobre comparação de arquivos de inicialização do shell mostra como os shells compatíveis com o bourne shell usam os profilearquivos, enquanto outros shells não. Isso ocorre porque, no passado, o shell inicial (aquele que iniciou o muxer) precisava ser um shell compatível com Bourne.

grochmal
fonte