Diferença entre o Shell de Login e o Shell Não-Login?


318

Entendo a diferença básica entre um shell interativo e um não interativo. Mas o que exatamente diferencia um shell de login de um shell que não é de login?

Você pode dar exemplos de usos de um shell interativo sem login ?


45
Eu acho que a pergunta é melhor formulada como " Por que devemos / devemos nos diferenciar de shells de login e não-login?" Muitos lugares na web já nos dizem quais são as diferenças, em termos de quais arquivos de inicialização cada um lê; mas nenhum deles parece responder ao "porquê" de maneira satisfatória e convincente. Exemplos de casos de uso em que você definitivamente não deseja um ou outro comportamento seriam ótimos.
Kal

2
@ Kal Isso teria que ser uma pergunta diferente, já que nenhuma resposta aqui realmente cobre isso. Edit: Na verdade, aqui está: POR QUE um shell de login sobre um shell que não é de login ? .
Skippy le Grand Gourou

Respostas:


304

Um shell de logon é o primeiro processo executado sob o seu ID de usuário quando você efetua login em uma sessão interativa. O processo de login informa ao shell que se comporte como um shell de login com uma convenção: passar o argumento 0, que normalmente é o nome do executável do shell, com um -caractere anexado (por exemplo, -bashenquanto seria normalmente bash. Os shells de login geralmente lêem um arquivo que faz coisas como definir variáveis ​​de ambiente: /etc/profilee ~/.profilepara o shell Bourne tradicional, ~/.bash_profileadicionalmente para o bash , /etc/zprofilee ~/.zprofilepara o zsh , /etc/csh.logine ~/.loginpara o csh, etc.

Quando você efetua login em um console de texto, através do SSH ou com su -, você obtém um shell de logon interativo . Quando você efetua login no modo gráfico (em um gerenciador de exibição X ), não recebe um shell de logon; em vez disso, obtém um gerenciador de sessões ou um gerenciador de janelas.

É raro executar um shell de logon não interativo , mas algumas configurações do X fazem isso quando você faz login com um gerenciador de exibição, para organizar a leitura dos arquivos de perfil. Outras configurações (isso depende da distribuição e do gerenciador de exibição) leem /etc/profilee ~/.profileexplicitamente, ou não as leem. Outra maneira de obter um shell de logon não interativo é efetuar logon remotamente com um comando passado através da entrada padrão que não é um terminal, por exemplo ssh example.com <my-script-which-is-stored-locally(ao contrário de ssh example.com my-script-which-is-on-the-remote-machine, que executa um shell não interativo e sem logon).

Ao iniciar um shell em um terminal em uma sessão existente (tela, terminal X, buffer do terminal Emacs, um shell dentro de outro etc.), você obtém um shell interativo e sem login . Esse shell pode ler um arquivo de configuração do shell ( ~/.bashrcpara o bash chamado como bash, /etc/zshrce ~/.zshrcpara zsh /etc/csh.cshrce ~/.cshrccsh, o arquivo indicado pela ENVvariável para shells compatíveis com POSIX / XSI, como dash, ksh e bash quando chamado como sh, $ENVse definido e ~/.mkshrcpara mksh etc.).

Quando um shell executa um script ou comando passado em sua linha de comando, é um shell não interativo e sem logon . Tais shells funcionam o tempo todo: é muito comum que quando um programa chama outro programa, ele realmente executa um pequeno script em um shell para invocar esse outro programa. Alguns shells lêem um arquivo de inicialização nesse caso (o bash executa o arquivo indicado pela BASH_ENVvariável, zsh executa /etc/zshenve ~/.zshenv), mas isso é arriscado: o shell pode ser chamado em todos os tipos de contextos, e dificilmente você pode fazer algo que possa não ser feito. quebrar alguma coisa.

Estou simplificando um pouco, veja o manual para detalhes sangrentos.


2
Você poderia dar um exemplo de como executar bashcomo um shell de logon não interativo?
Piotr Dobrogost

13
@PiotrDobrogostecho $- | bash -lx
Gilles

1
Não sei se isso é verdade em geral, mas quero observar que, quando abro um novo terminal (no osx usando as configurações padrão), recebo um shell de login, embora nunca digite meu nome de usuário ou senha.
Kevin Wheeler

4
@KevinWheeler No OSX, por padrão, o aplicativo Terminal executa um shell de login. (Como explico, o programa que inicia o shell decide se o shell atua como um shell de login.) Essa não é a maneira normal de fazer as coisas.
Gilles

2
@IAmJulianAcosta Se FOOé uma variável de ambiente (ou seja, .profilecontém export FOO=something), está disponível para todos os subprocessos, inclusive foo.sh. Se você alterar .profilepara export FOO=something_else, ./foo.shele ainda será impresso somethingaté a próxima vez que você fizer login.
Gilles

48

Para saber se você está em um shell de login:

prompt> echo $0
-bash # "-" is the first character. Therefore, this is a login shell.

prompt> echo $0
bash # "-" is NOT the first character. This is NOT a login shell.

No Bash, você também pode usar shopt login_shell:

prompt> shopt login_shell
login_shell     off

(ou onem um shell de login).

As informações podem ser encontradas em man bash(procure por Invocação). Aqui está um trecho:

Um shell de logon é aquele cujo primeiro caractere do argumento zero é um - ou iniciado com a opção --login.

Você pode testar isso sozinho. Sempre que você SSH, você está usando um shell de login. Por exemplo:

prompt> ssh user@localhost
user@localhost's password:
prompt> echo $0
-bash

A importância de usar um shell de login é que quaisquer configurações /home/user/.bash_profileserão executadas. Aqui está um pouco mais de informação se você estiver interessado (de man bash)

"Quando o bash é chamado como um shell de login interativo ou como um shell não interativo com a opção --login, 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 comandos a partir do primeiro que existe e é legível. a opção --noprofile pode ser usado quando o shell é iniciado para inibir este comportamento."


23

Em um shell de logon argv[0][0] == '-',. É assim que ele sabe que é um shell de login.

E então, em algumas situações, ele se comporta de maneira diferente, dependendo do status "shell de login". Por exemplo, um shell, que não é um shell de login, não executaria um comando "logout".


4
De acordo com man bash, com ênfase acrescentou: "A shell de login é aquele cujo primeiro caractere do argumento zero é um -, ou um iniciado com a opção --login. "
Wildcard

18

Um shell iniciado em um novo terminal em uma GUI seria um shell interativo sem logon. Seria fonte do seu .bashrc, mas não do seu .profile, por exemplo.


4

Vou elaborar a ótima resposta de Gilles, combinada com o método de Timothy para verificar o tipo de shell de login.

Se você gosta de ver as coisas por si mesmo, tente os trechos e cenários abaixo.

Verificando se o shell é (não) interativo

if tty -s; then echo 'This is interactive shell.'; else echo 'This is non-interactive shell.'; fi

Verificando se o Shell é (Não) Login

Se a saída echo $0começar com -, é o shell de login ( echo $0exemplo de saída:) -bash. Caso contrário, é um shell que não é de login ( echo $0exemplo de saída:) bash.

if echo $0 | grep -e ^\- 2>&1>/dev/null; then echo "This is login shell."; else echo "This is non-login shell."; fi;

Vamos combinar os dois acima para obter as duas informações de uma vez:

THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; 
THIS_SHELL_LOGIN_TYPE='non-login'; 
if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; 
if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

Cenários:

Sessão SSH típica sem opções especiais

ssh ubuntu@34.247.105.87
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

ubuntu@ip-172-31-0-70:~$ THIS_SHELL_INTERACTIVE_TYPE='non-interactive';
ubuntu@ip-172-31-0-70:~$ THIS_SHELL_LOGIN_TYPE='non-login';
ubuntu@ip-172-31-0-70:~$ if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi;
ubuntu@ip-172-31-0-70:~$ if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
ubuntu@ip-172-31-0-70:~$ echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

interactive/login

Executando script ou executando explicitamente via novo shell

ubuntu@ip-172-31-0-70:~$  bash -c 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; 
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

Executando script local remotamente

ssh ubuntu@34.247.105.87 < checkmy.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

non-interactive/login

Executando um comando sobre o ssh remotamente

ssh ubuntu@34.247.105.87 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

non-interactive/non-login

Executando um comando sobre ssh remotamente com -tswitch

Você pode solicitar explicitamente o shell interativo quando desejar executar o comando remotamente via ssh usando -tswitch.

ssh ubuntu@34.247.105.87 -t 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

Nota: No tópico por que executar o comando remotamente não é login shellmais informações aqui .

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.