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 ?
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 ?
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 normalmente bash
. 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 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 ( ~/.bashrc
para o bash chamado como bash
, /etc/zshrc
e ~/.zshrc
para zsh /etc/csh.cshrc
e ~/.cshrc
csh, o arquivo indicado pela ENV
variável para shells compatíveis com POSIX / XSI, como dash, ksh e bash quando chamado como sh
, $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.
bash
como um shell de logon não interativo?
echo $- | bash -lx
FOO
é uma variável de ambiente (ou seja, .profile
contém export FOO=something
), está disponível para todos os subprocessos, inclusive foo.sh
. Se você alterar .profile
para export FOO=something_else
, ./foo.sh
ele ainda será impresso something
até a próxima vez que você fizer login.
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 on
em 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_profile
serã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_login
e~/.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".
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. "
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 $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
.
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"
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
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
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
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
-t
switchVocê pode solicitar explicitamente o shell interativo quando desejar executar o comando remotamente via ssh usando -t
switch.
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 shell
mais informações aqui .