De acordo com man sshd
:
LOGIN PROCESS
When a user successfully logs in, sshd does the following:
<...>
9. Runs user's shell or command. All commands are run under the
user's login shell as specified in the system password data‐
base.
Não está claro, porém, "executar sob o shell de login do usuário" significa literalmente "shell de login, como em bash -l
"? Minhas experiências mostram que não, não é:
$ ssh u@h shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Not login shell
Eu não posso ver por que isso é assim? Isso resulta em comandos sendo executados, não obtendo o ambiente usual, pois apenas faz login no shell. Isso é complicado.
shell de login pode significar duas coisas diferentes nesse contexto:
o shell que é definido como o shell de login para o usuário no banco de dados da conta.
Por exemplo:
/bin/zsh
é o meu shell de login, o 7º campo na minha entrada no banco de dados da conta. Alguns outros usuários podem ter/bin/tcsh
,/bin/fish
,/bin/bash
,/sbin/nologin
,/bin/false
...uma invocação de um shell usado para inicializar uma sessão de
argv[0]
login , aquelas que geralmente são feitas por login /-
sshd-l
...--login
como.profile
,.login
,.zlogin
, etc.Em qualquer caso, o
sh
inssh
é para shell e,sshd
comorshd
antes, sempre invoca um shell para interpretar o código enviado pelo cliente, se houver.Se você executar:
Onde
foo
ebar
os argumentos são passados parassh
,ssh
junta-os com espaços e envia ofoo bar
código shell para o servidor.O servidor
host
executará o shell de loginuser
com 3 argumentos:zsh
-c
foo bar
nesse exemploE o shell interpretará isso como código em sua própria sintaxe¹, não será executado como um shell de login,
argv[0]
não começa com um arquivo-
.Se nenhum argumento for passado para o cliente, como quando é invocado como:
rlogin
Em seguida, entra-se no modo (comorsh
aquele usado para executarrlogin
quando não é passado um comando), então um pseudo-tty é usado esshd
executa o shell de login do usuário com apenas um argumento (argv[0]
):-
, no meu caso-zsh
.E isso diz ao shell que ele está sendo executado como um shell de login e ele irá ler
.zprofile
/.profile
/.login
.Entao, para resumir:
ssh host shell-code
é comorsh host shell-code
e executa um comando remotamente fazendo com que o shell de login do usuário remoto analise algum código.ssh host
é comorlogin host
, e efetua login remotamente iniciando seu shell de login no modo de shell de login em um terminal virtual.¹ para este muito simples, exceto para
/bin/false
ou/sbin/nologin
é claro e talvez para usuários que gostam de ter/usr/bin/python3
como shell de login, o código será interpretado da mesma forma por todos os shells, mas para os mais complexos, haverá alguma variação. Veja também Como executar um comando simples arbitrário sobre ssh sem conhecer o shell de login do usuário remoto?Não, o SSH apenas invoca um shell de login ao fazer login em um shell, não ao executar um comando. Isso significa que, se você deseja que seus arquivos de inicialização de login sejam executados (por exemplo
~/.profile
, ), você precisa fazer isso explicitamente. Esta é uma escolha de design deliberada: nos dias em que a maioria dos logins era em um terminal de texto, muitos usuários executavam comandos em seus.profile
que só faziam sentido ao fazer login para uma sessão interativa. (Isso é muito menos comum agora que a maioria das pessoas faz login localmente em uma sessão gráfica.) Você não gostaria de um rápidossh example.com ls
, ou pior, umrsync example.com:somefile .
, para iniciar o Emacs e ligar seu modem para buscar seu e-mail!O comando no SSH é uma string, obtida pela concatenação dos argumentos da linha de comando com um espaço entre eles. Por exemplo,
ssh u@h shopt -q login_shell
executa o comandoshopt -q login_shell
. É exatamente equivalente assh u@h 'shopt -q login_shell'
, oussh u@h 'shopt -q' login_shell
, etc.O SSH passa essa string para o shell de login do usuário. O SSH não conhece nenhum outro shell. O servidor pode estar executando em um sistema não-Unix ou em um ambiente restrito onde não há nenhum programa chamado
sh
oubash
.O servidor SSH executa o executável listado no banco de dados do usuário como o shell de login do usuário, mas não necessariamente como um shell de login. Quando a linha de comando não está vazia, ela passa uma lista de três argumentos:
argv[0]
é o nome base do programa, seguindo a convenção usual.argv[1]
é a corda-c
.argv[2]
é o comando passado pelo cliente.Para uma linha de comando vazia, o servidor SSH chama o shell de login do usuário como um shell de login . Isso significa uma lista de um argumento:
argv[0]
é um traço (-
) seguido do nome base do programa.Por exemplo, aqui está a saída de
ssh localhost 'cat /proc/$$/cmdline | tr \\0 \\n'
em uma máquina Linux:Para um shell de login, é mais difícil de observar, porque o próprio shell de login geralmente executa outros programas. A maneira mais fácil de ver o que está acontecendo é desabilitar temporariamente o(s) arquivo(s) de inicialização do shell de login, por exemplo, renomeando temporariamente
~/.profile
(ou~/.bash_profile
,~/.zprofile
, etc. dependendo de qual shell você usa). Aqui está um exemplo em uma conta com/bin/sh
o shell de login: