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, -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.
bashcomo um shell de logon não interativo?
echo $- | bash -lx
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.
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."
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 $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"
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
-tswitchVocê 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 .