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 ?
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.
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.
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.
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."
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".
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.
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:
ssh ubuntu@34.247.105.87Welcome to Ubuntu16.04.5 LTS (GNU/Linux4.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 Ubuntu16.04.5 LTS (GNU/Linux4.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 .
Respostas:
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,-bash
enquanto seria normalmentebash
. Os shells de login geralmente lêem um arquivo que faz coisas como definir variáveis de ambiente:/etc/profile
e~/.profile
para o shell Bourne tradicional,~/.bash_profile
adicionalmente para o bash † ,/etc/zprofile
e~/.zprofile
para o zsh † ,/etc/csh.login
e~/.login
para 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/profile
e~/.profile
explicitamente, 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 exemplossh example.com <my-script-which-is-stored-locally
(ao contrário dessh 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 (
~/.bashrc
para o bash chamado comobash
,/etc/zshrc
e~/.zshrc
para zsh/etc/csh.cshrc
e~/.cshrc
csh, o arquivo indicado pelaENV
variável para shells compatíveis com POSIX / XSI, como dash, ksh e bash quando chamado comosh
,$ENV
se definido e~/.mkshrc
para 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_ENV
variável, zsh executa/etc/zshenv
e~/.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.
fonte
bash
como um shell de logon não interativo?echo $- | bash -lx
FOO
é uma variável de ambiente (ou seja,.profile
contémexport FOO=something
), está disponível para todos os subprocessos, inclusivefoo.sh
. Se você alterar.profile
paraexport FOO=something_else
,./foo.sh
ele ainda será impressosomething
até a próxima vez que você fizer login.Para saber se você está em um shell de login:
No Bash, você também pode usar
shopt login_shell
:(ou
on
em um shell de login).As informações podem ser encontradas em
man bash
(procure por Invocação). Aqui está um trecho:Você pode testar isso sozinho. Sempre que você SSH, você está usando um shell de login. Por exemplo:
A importância de usar um shell de login é que quaisquer configurações
/home/user/.bash_profile
serão executadas. Aqui está um pouco mais de informação se você estiver interessado (deman bash
)fonte
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".
fonte
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. "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.
fonte
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
Verificando se o Shell é (Não) Login
Se a saída
echo $0
começar com-
, é o shell de login (echo $0
exemplo de saída:)-bash
. Caso contrário, é um shell que não é de login (echo $0
exemplo de saída:)bash
.Vamos combinar os dois acima para obter as duas informações de uma vez:
Cenários:
Sessão SSH típica sem opções especiais
Executando script ou executando explicitamente via novo shell
Executando script local remotamente
Executando um comando sobre o ssh remotamente
Executando um comando sobre ssh remotamente com
-t
switchVocê pode solicitar explicitamente o shell interativo quando desejar executar o comando remotamente via ssh usando
-t
switch.Nota: No tópico por que executar o comando remotamente não é
login shell
mais informações aqui .fonte